poj1678 极小极大算法

题意:给n个数,并给一个区间[a,b],第一次选的数要在这个区间内,然后每次选n个数中的某个数,使得这个数减去对手所选的数得到的差值在[a,b]区间内。
要求第一个选手所选的数的和减去第二个人所选的数的和的最大差值。
a>0,很明显每次选的数只可能比上次所选的数大,所以把这n个数进行排序。
dp[i]表示选择i位置的数所能得到的最大差值。

小盆友1必取第i位置上的数,这是我们的定义,小盆友2很聪明,他就不想让小盆友1取得最大值,于是,小盆友2选择可取的j中dp[j]最大的一个,这样dp[i]就小盆友1从这里取的差值就小了。

    既:dp[i]=a[i]-max{dp[j]}。

 

ccy代码:

#include<iostream>
using namespace std;

const int maxn=10010;

int a[maxn];
int dp[maxn];
int Case,n,A,B;

void qsort(int l,int r)
{
    int i=l,j=r,mid=a[(l+r)>>1];
    while (i<j)
    {
        while (a[i]<mid) i++;
        while (mid<a[j]) j--;
        if (i<=j)
        {
            swap(a[i],a[j]);
            i++; j--;
        }
    }
    if (l<j) qsort(l,j);
    if (i<r) qsort(i,r);
}

int DP()
{
    for (int i=n;i>=1;i--)//从后往前坐
    {
        int MAX=INT_MIN;//注意是INT_MIN,因为数字中有负数
        bool flag=false;//标志是否有可取的j
        for (int j=i+1;j<=n;j++)
        {
            int cz=a[j]-a[i];//差值
            if (B<cz) break;//因为已经排了序,所以可以提前退出
            if (A<=cz && cz<=B)
            {
                flag=true;
                MAX=max(MAX,dp[j]);//小盆友2很聪明,他要让被减数尽可能的大,这样,差值就尽可能的小,他就是不要如小盆友1的意
            }
        }
        if (!flag) MAX=0;//如果flag==false,说明小盆友2没有办法再取数,游戏结束,后面无差值,所以MAX=0
        dp[i]=a[i]-MAX;
    }
    bool flag=false;
    int MAX=INT_MIN;
    for (int i=1;i<=n;i++)//选小盆友1可以取的第一个数中dp最大那个数
    {
        if (A<=a[i] && a[i]<=B)
        {
            flag=true;
            MAX=max(MAX,dp[i]);
        }
        if (B<a[i]) break;
    }
    if (!flag) MAX=0;//如果flag==false,说明连小盆友1都没法下手选,最后结果差值当然为0
    return MAX;
}

int main()
{
    scanf("%d",&Case);
    while (Case>0)
    {
        Case--;
        scanf("%d%d%d",&n,&A,&B);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        qsort(1,n);//排序
        printf("%d\n",DP());
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值