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的楼教主,然后这题就没了,把时间都花别的地方去了,以后还是应该听从榜的召唤跟一下榜。