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;
}

 

posted @ 2012-12-09 23:15  _hikaru__  阅读(387)  评论(0编辑  收藏  举报