poj 1678
看别人把这题分到博弈去了,DP的成分更大一点。。
输入t,t组数据,输入n,a,b;n个数。。
两个人取数,A取第一个数0<a<=x1<=b,B取a<=x2-x1<=b;以此类推到不能取为止,sum1=A取数之和,sum2=B取数之和。A要使sum1-sum2最大,B则尽量让sum1-sum2小。而他们都会取最佳的数,即A:MAX(sum1-sum2);B:MAX(sum2-sum1),因此两个人的状况是等同的,所以后面的策略都是固定的。
不妨设dp[i]为取第i个数能得到的最大值。
而其实对于A和B来说,都有
dp[i]=num[i]-max{dp[j]|i<j&&a<=num[j]-num[i]<=b}
从后面往前面推,然后遍历a<=num[i]<=b的数的dp[i],找最大值即答案。
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #define N 10010 #define inf (1<<25) using namespace std; int dp[N],num[N]; int main () { int t,n,a,b; int i,j,k; int max; scanf("%d",&t); while (--t>=0) { scanf("%d%d%d",&n,&a,&b); for (i=0;i<n;++i) scanf("%d",&num[i]); sort(num,num+n); memset(dp,0,sizeof(dp)); dp[n-1]=num[n-1]; for (i=n-2;i>=0&&num[i]>=a;--i) { max=-inf; for (j=i+1;num[j]-num[i]<=b&&j<n;++j) { if (num[j]-num[i]<a) continue; if (max<dp[j]) max=dp[j]; } if (max!=-inf) dp[i]=num[i]-max; else dp[i]=num[i]; } max=-inf; for (i=0;num[i]<a&&i<n;++i); for (;i<n&&num[i]<=b;++i) if (max<dp[i]) max=dp[i]; printf("%d\n",max==-inf?0:max); } return 0; }