您的位置:首页 > 其它

POJ-1678 I Love this Game!(博弈论)

2016-07-20 11:05 411 查看
题目链接

POJ-1678 I Love this Game!

题目大意

给定n个数,两人轮流取递增的数,先手先取[a,b]内的数,此后,后取的数与前一个数的差值在[a,b]内,求先手获得数的和减去后手获得数的和的最大值?

Sample Input

3

6 1 2

1 3 -2 5 -3 6

2 1 2

-2 -1

2 1 2

1 0

Sample Output

-3

0

1

思路

这种博弈DP以前做过很多次,但是这回状态是不连续的就不知道怎么转移了,其实只用记忆化搜索即可。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int INF=0x3f3f3f3f;

int n,a,b,dp[10005];//dp[i]表示先手取第i个数时能获得的最大分差
int num[10005];

int DP(int i) {
if(dp[i]!=-INF) {
return dp[i];
}
int opp=-INF;//对手在这种情况下能获得的最大分差
for(int j=i+1;j<n;++j) {//由于都是最优策略,所以对手一定会选择分差最大的取法
if(a<=num[j]-num[i]&&num[j]-num[i]<=b) {
opp=max(opp,DP(j));
}
}
if(opp==-INF) {
dp[i]=num[i];
}
else {
dp[i]=num[i]-opp;
}
return dp[i];
}

int solve() {
int ans=-INF;
for(int i=0;i<n;++i) {
if(a<=num[i]&&num[i]<=b) {
ans=max(ans,DP(i));
}
}
return ans==-INF?0:ans;
}

int main() {
int T;
scanf("%d",&T);
while(T-->0) {
scanf("%d%d%d",&n,&a,&b);
for(int i=0;i<n;++i) {
scanf("%d",num+i);
dp[i]=-INF;
}
sort(num,num+n);
printf("%d\n",solve());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  博弈论 DP