• 【记忆化搜索】Navy maneuvers


    【来源】:

    2008年哈尔滨区域赛题目

    【题目链接】:

    http://acm.hdu.edu.cn/showproblem.php?pid=2452

    【参考博客】:

    https://blog.csdn.net/watermuch/article/details/9465185

    【题意】:

    真的要好好检讨,英语不好,这个题就别想做了。

    意译一波,就是船是有两位领导  进行领航,一位叫做V,另一位叫G。

    给出一幅有向无环图,每一个节点都有一个权值,如果经过这个节点都会获得对应的权值。

    从一个入度为0的节点开始,到某个出度为0的节点停止。

    但是两个人的想法不同:

    V想要权值和尽可能大,G想要权值和尽可能小。

    最后问,给出一个F,如果在一波操作之后获得的权值和大于等于F则”V胜利“,否则就”G荣誉“。


    【题解】:

    在图上跑DAG最长路,边记录对应的dp值,边跑,如果当前领航的人是谁,就分别写出对应的走法。

    一定需要记忆化搜索,主要是因为多个起点,记忆化尽可能减少复杂度。


    【代码】:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e4+10;
     4 
     5 vector<int>G[N];
     6 int dp[N][2],w[N],du[N];
     7 int n,m,f;
     8 
     9 /*
    10     多组输入,记住要清空
    11 */
    12 void Init(){
    13     for(int i=0;i<=n;i++){
    14         du[i] = dp[i][0] = dp[i][1] = 0 ;
    15         G[i].clear();
    16     }
    17 }
    18 /*
    19     DAG记忆化搜索
    20     dp[i][1/0]
    21     对于第i个节点来说:
    22     [1]——V在领航,他想要权值最大化。
    23     [0]——G在领航,他想要权值最小化。
    24 
    25 */
    26 
    27 int dfs(int u,int cur){
    28 
    29     cur %= 2 ;
    30     if( dp[u][cur] ) return dp[u][cur];
    31 
    32     int Size = G[u].size() ;
    33     if( Size == 0 ) return w[u] ;
    34 
    35     int maxz = -1 , minz = 0x3f3f3f3f;
    36     for(int i=0;i<Size;i++){
    37         int to = G[u][i];
    38         /*
    39             请注意V,G交替领航,当前位置来说,下一个点是最大化还是最小化、
    40             1——Max
    41             0——Min
    42         */
    43         if( cur ){
    44             maxz = max( maxz , dfs(to,cur+1) ) ;
    45         }else{
    46             minz = min( minz , dfs(to,cur+1) ) ;
    47         }
    48     }
    49 
    50     /*
    51         但是过程中的节点的权值都会被记录并返回到上面的for里面。
    52         
    53     */
    54     if( cur ) return dp[u][cur] = maxz + w[u] ;
    55     else return dp[u][cur] = minz + w[u] ;
    56 }
    57 int main()
    58 {
    59     while(~scanf("%d%d%d",&n,&m,&f)){
    60         Init();
    61         for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    62         for(int i=1,u,v;i<=m;i++){
    63             scanf("%d%d",&u,&v);
    64             G[u].push_back(v);
    65             du[v] ++ ;
    66         }
    67         /*
    68             ∵V先手领航
    69             ∴他的目标就是让自己的值最大化,使其大于等于f.
    70         */
    71         int maxz = -1 ;
    72         for(int i=1;i<=n;i++){
    73             //题目要求要从入度为0的节点开始.
    74             if( !du[i] ){
    75                 maxz = max( maxz , dfs(i,1) ) ;
    76             }
    77         }
    78         if( maxz >= f ) puts("Victory");
    79         else    puts("Glory");
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    WCF系列(五) 也谈序列化(下)
    优秀程序员的十个习惯
    WCF系列(九) WCF安全系列(四) WSHttpBinding绑定之Transport安全模式
    TCP/IP 协议简单分析
    技巧:在Silverlight应用程序中进行数据验证
    WCF系列(三) WCF配置文件注释
    [转]ASP.NET(C#)常用代码30例
    服务器端 在iframe中控制父窗体div并调用父窗体Button
    GridView的模版列中加入按钮,触发按钮事件后,如何获取该行的某个值?
    通用分页 模块
  • 原文地址:https://www.cnblogs.com/Osea/p/11323901.html
Copyright © 2020-2023  润新知