• 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 }
  • 相关阅读:
    windows安全实验
    ping 命令的禁止 以及密码的攻破
    网络基础
    html 中间件
    js php BurpSuite v2.1
    网页标签,PHPstudy
    说说text_line_orientation算子的巧妙应用
    说说C#进行数字图像处理的方法
    微信张小龙产品30条
    说说几个常用的阈值分割算子
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6298396.html
Copyright © 2020-2023  润新知