ACM-ICPC 2018 徐州赛区网络预赛 B. BE, GE or NE <<DP

题意

两个人在一起玩galgame,一个人想看good ending,另一个想看bad ending,两个人轮流选选项都按最优策略选,问最后能看到什么结局。

思路

可以理解为一个人想让最终分数尽可能高,另一个想让最终分数尽可能低,然后根据每个问题双向dp,一下子就写出来了。

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1005;
 4 struct selection{
 5     int a,b,c;
 6 };
 7 selection option[N];
 8 int dp[N][205];
 9 int n,m,k,l;
10 int dfs(int now,int score)
11 {
12     if(now==n+1) return score;
13     if(dp[now][score]!=-1) return dp[now][score];
14     selection &nn=option[now];
15     if(now%2!=0){
16         int ret=-1;
17         if(option[now].a)
18             ret=max(dfs(now+1,score+nn.a>200?200:score+nn.a),ret);
19         if(option[now].b)
20             ret=max(dfs(now+1,score-nn.b<0?0:score-nn.b),ret);
21         if(option[now].c)
22             ret=max(dfs(now+1,200-score),ret);
23         dp[now][score]=ret;
24     }
25     else{
26         int ret=300;
27         if(option[now].a)
28             ret=min(dfs(now+1,score+nn.a>200?200:score+nn.a),ret);
29         if(option[now].b)
30             ret=min(dfs(now+1,score-nn.b<0?0:score-nn.b),ret);
31         if(option[now].c)
32             ret=min(dfs(now+1,200-score),ret);
33         dp[now][score]=ret;
34     }
35     return dp[now][score];
36 }
37 int main()
38 {
39     scanf("%d%d%d%d",&n,&m,&k,&l);
40     for(int i=1,a,b,c;i<=n;i++)
41     {
42         scanf("%d%d%d",&a,&b,&c);
43         option[i]={a,b,c};
44     }
45     memset(dp,-1,sizeof(dp));
46     int ans=dfs(1,m+100);
47     if(ans>=k+100) printf("Good Ending\n");
48     else if(ans>l+100) printf("Normal Ending\n");
49     else printf("Bad Ending\n");
50     return 0;
51 }

后记

这题赛时没想出来,一开始觉得是博弈,后来想了想隐隐感觉是dp,但是没下手做,丢给了不会dp的楼教主,然后这题就没了,把时间都花别的地方去了,以后还是应该听从榜的召唤跟一下榜。

posted @ 2018-09-11 22:51  computer_luo  阅读(217)  评论(0编辑  收藏  举报