题目链接: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