51nod1489(dfs)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1489

题意:中文题诶~

思路:dfs

首先我们要通过攻击第1个人和倒数第2个人来杀死第一个和最后一个人。

接下来我们考虑如何最高效的杀死中间的人:

假设当前我们正在攻击第pos个人,那么我们要保证第pos-1个人已死才能移向下一个人(这点很好理解,因为我们如果在攻击第pos个人以前没有杀死第pos-1个人,那么我们就无法杀死它)。不过我们还要再具体一点讨论这些情况:

1.如果我们在攻击第pos个人死,第pos个人已经死了,我们还没有杀死第pos-1个人,那么我们需要继续攻击第pos个人直至pos-1死亡(因为我们是用的dfs,所以不需要考虑返回去直接攻击第pos-1个人);

2.如果我们攻击第pos个人,pos还没死,pos-1已经死了,假设我们攻击cnt次杀死了pos-1,攻击cc次能杀死pos,那么我们需要遍历攻击cnt~cc次攻击后进入下一层递归的所有情况;

取得的最优解就是我们要的答案啦.....

代码:

 1 #include <bits/stdc++.h>
 2 #define MAXN 50
 3 #define inf 0x3f3f3f3f
 4 using namespace std;
 5
 6 int gg[MAXN], ans=inf, n, a, b;
 7
 8 void dfs(int pos, int num){
 9     int cnt=0, cc=0; //***注意这里的cnt一定要赋初值,因为有可能满足(cc>cnt&&gg[pos]>=0)条件时不满足(gg[pos-1]>=0)条件
10     if(pos==n){  //***到达第n个人是返回并更新攻击次数
11         ans=min(ans, num);
12         return;
13     }
14     if(gg[pos-1]<0){ //***只有前一个人死了才能向后移动
15         dfs(pos+1, num);
16     }
17     if(gg[pos-1]>=0){ //***只处理大于等于0的情况
18         cnt=gg[pos-1]/b+1;
19         gg[pos-1]-=b*cnt;
20         gg[pos]-=a*cnt;
21         gg[pos+1]-=b*cnt;
22         dfs(pos+1, num+cnt);  
23         gg[pos-1]+=b*cnt;  //***注意回溯时要将前面改变的量复原
24         gg[pos]+=a*cnt;
25         gg[pos+1]+=b*cnt;
26     }
27     cc=gg[pos]/a+1;
28     if(cc>cnt&&gg[pos]>=0){ //***如果此时pos-1已死而pos还活着的话,我们可以选择直接将其杀死再移向下一个或者直接移向下一位
29         for(int i=cnt+1; i<=cc; i++){
30             gg[pos-1]-=b*i;
31             gg[pos]-=a*i;
32             gg[pos+1]-=b*i;
33             dfs(pos+1, num+i);
34             gg[pos-1]+=b*i;
35             gg[pos]+=a*i;
36             gg[pos+1]+=b*i;
37         }
38     }
39     return;
40 }
41
42 int main(void){
43     int num=0;
44     cin >> n >> a >> b;
45     for(int i=1; i<=n; i++){
46         cin >> gg[i];
47     }
48     int cnt=gg[1]/b+1; //***先去头
49     num+=cnt;
50     gg[1]-=b*cnt;
51     gg[2]-=a*cnt;
52     gg[3]-=b*cnt;
53     if(gg[n]>=0){  //***去尾,注意如果只有三个人的话有可能gg[n]此时已经小于0了
54         cnt=gg[n]/b+1;
55         num+=cnt;
56         gg[n-2]-=b*cnt;
57         gg[n-1]-=a*cnt;
58         gg[n]-=b*cnt;
59     }
60     dfs(2, 0);
61     if(ans==inf){ //***注意有可能dfs直接满足条件退出了,此时ans值为inf
62         ans=0;
63     }
64     cout << ans+num << endl;
65     return 0;
66 }
时间: 2024-10-13 02:49:50

51nod1489(dfs)的相关文章

解救小哈——DFS算法举例

一.问题引入 有一天,小哈一个人去玩迷宫.但是方向感不好的小哈很快就迷路了.小哼得知后便去解救无助的小哈.此时的小哼已经弄清楚了迷宫的地图,现在小哼要以最快的速度去解救小哈.那么,问题来了... 二.问题的分析 首先我们用一个二维数组来存储这个迷宫,刚开始的时候,小哼处于迷宫的入口处(1,1),小哈在(p,q).其实这道题的的本质就在于找从(1,1)到(p,q)的最短路径. 此时摆在小哼面前的路有两条,我们可以先让小哼往右边走,直到走不通的时候再回到这里,再去尝试另外一个方向. 在这里我们规定一

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

uva1103(dfs)

UVA - 1103 还是没写好,,看的别人的 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <cstdlib> 7 #include <stack> 8 #include <cctype> 9 #include <str

poj 1088 滑雪 DP(dfs的记忆化搜索)

题目地址:http://poj.org/problem?id=1088 题目大意:给你一个m*n的矩阵 如果其中一个点高于另一个点 那么就可以从高点向下滑 直到没有可以下滑的时候 就得到一条下滑路径 求最大的下滑路径 分析:因为只能从高峰滑到低峰,无后效性,所以每个点都可以找到自己的最长下滑距离(只与自己高度有关).记忆每个点的最长下滑距离,当有另一个点的下滑路径遇到这个点的时候,直接加上这个点的最长下滑距离. dp递推式是,dp[x][y] = max(dp[x][y],dp[x+1][y]+

蓝桥杯 大臣的旅费_树的最长度_两次DFS

#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <functional> #include <vector> using namespace std; const int maxn = 1000000 + 10; const int INF = 10000000

A. The Fault in Our Cubes 暴力dfs

http://codeforces.com/gym/101257/problem/A 把它固定在(0,0, 0)到(2, 2, 2)上,每次都暴力dfs检查,不会超时的,因为规定在这个空间上,一不行,就会早早退出. 这样写起来比较好写. #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <

codeforces717E Paint it really, really dark gray(树上dfs)

题意: 给你一棵树,2e5个节点,每个节点有一种颜色(黑色或粉色) 让你从节点1开始,自由沿边行走,到达节点时会把这个节点的颜色改变 要求你输出任意一条路径使得从节点1出发,所有节点的颜色都变为黑色 思路: 很明显要递归遍历 每到达一个节点就先改变节点的颜色标志并输出当前节点 如果当前到达了叶子节点,则不用进行操作 返回上层节点时再改变节点的颜色标志并输出当前节点,然后判断叶子节点的颜色,如果为粉色,则再到达一次叶子节点再回到当前节点 这样确保当前节点的所有儿子节点都为黑色的 然后就这样一直递归

POJ2488 dfs

A Knight's Journey Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 41972   Accepted: 14286 Description Background The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey ar

BZOJ_1016_[JSOI2008]_最小生成树计数_(dfs+乘法原理)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1016 给出一张图,其中具有相同权值的边的数目不超过10,求最小生成树的个数. 分析 生成树的计数有一个什么什么算法... 我真的企图研究了...但是智商捉急的我实在看不懂论文... 所以最后还是写了暴力... 当然暴力也要靠正确的姿势的. 首先来看一个结论: 同一张图的所有最小生成树中,边权值相同的边的数目是一定的. 也就是说,假如某一张图的某一棵最小生成树由边权值为1,1,2,2,2,3的