标签:alt 个人 ali ++ AC none return def 没有
之前在某个可怕的比赛中看到了博弈论的签到题,但是由于三个人没有一个学过博弈论以至于强行放弃的事故发生。我决定立刻,马上开坑博弈论专题。
首先分析题目,可以发现,a,b的具体大小大于0,则这意味着每次选取的时候后一个数必然大与前一个数字。因此具有单调性,可以先将数组排序。(按照这个道理其实可以去除掉所有小于a的数字)
其次,首先假设dp[i]代表当先手面临arr[i]时的最优选择,则,应当认为,每次状态转移的目的实际上是在替后手做决策——在当前状态选取最小收益的点作为后续选择。
最后考虑特殊点——游戏结束点,dp[i]应当为arr[i]本身。
#include<iostream> #include<stdlib.h> #include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> #include<vector> #include<set> #include<map> #include<queue> using namespace std; #define ll long long const ll MAXN=100233; const ll INF = (ll)1<<40; ll arr[MAXN]; ll dp[MAXN]; ll n,a,b; void init() { cin>>n>>a>>b; for(int i=0;i<n;++i) cin>>arr[i]; sort(arr,arr+n); for(int i= n-1;i>=0;--i) { dp[i] = INF; for(int j=i+1;j<n;++j) { if(arr[j]<arr[i]+a)continue; if(arr[j]>arr[i]+b)break; dp[i] = min(arr[i] - dp[j],dp[i]); } if(dp[i] == INF)dp[i] = arr[i]; } ll ans = -INF; for(int i=0;i<n;++i) { if(arr[i] < a)continue; if(arr[i] > b)break; ans = max(dp[i],ans); } if(ans == -INF)ans = 0; cout<<ans<<"\n"; } int main() { int t; cin>>t; while(t--) init(); return 0; }
标签:alt 个人 ali ++ AC none return def 没有
原文地址:https://www.cnblogs.com/rikka/p/9074864.html