POJ 2287 Tian Ji -- The Horse Racing

题目链接

题目大意

田忌赛马的故事。赢一局给200块(“silver dollar”银美元大概是银两),平局不给钱,输一局赔两百块,问最大获利。

思路

这个题大概是个贪心。但是偏不用贪心解。
考虑田忌的出马顺序。当齐王的马是从高到低出时,田忌最优情况下只会有两种选择。

  • 出当前最强的马,去赢下这一场或平局。
  • 出当前最菜的马,故意输掉或平局。

那么就可以DP。 f[i][j] f [ i ] [ j ] 表示已经进行了 i i 轮(也就是齐王出到了第i高的马),田忌出了前 j j 高的马。
转移很好想,设win(i,j)返回能力值分别为 i i j的两匹马的胜负关系, A[] A [ ] 存储田忌的马, B[] B [ ] 存储齐王的马。

f[i][j]=max{f[i1][j1]win(A[j],B[i]),f[i1][j]win(A[(n(ji)+1)],B[i])} f [ i ] [ j ] = m a x { f [ i − 1 ] [ j − 1 ] ∗ w i n ( A [ j ] , B [ i ] ) , f [ i − 1 ] [ j ] ∗ w i n ( A [ ( n − ( j − i ) + 1 ) ] , B [ i ] ) }

代码
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<map>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<cctype>
#define pa pair<int,int>
#define INF 0x3f3f3f3f
#define inf 0x3f
#define fi first
#define se second
#define mp make_pair
#define ll long long
#define ull unsigned long long
#define pb push_back

using namespace std;

inline ll read()
{
    long long f=1,sum=0;
    char c=getchar();
    while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}
    while (isdigit(c)) {sum=sum*10+c-'0';c=getchar();}
    return sum*f;
}
const int MAXN=1010;
int f[MAXN][MAXN],a[MAXN],b[MAXN];
int win(int i,int j)
{
    return i>j?1:i<j?-1:0;
}
int cmp(int i,int j){return i>j;}
int main()
{
    int n;
    scanf("%d",&n);
    while (n)
    {
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+1+n,cmp);
        for (int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        sort(b+1,b+1+n,cmp);
        memset(f,0x8f,sizeof(f));
        f[0][0]=0;
        for (int i=1;i<=n;i++)
        {
            for (int j=0;j<=i;j++)
            {
                if (j) f[i][j]=max(f[i][j],f[i-1][j-1]+win(a[j],b[i])*200);
                if (j!=i) f[i][j]=max(f[i][j],f[i-1][j]+win(a[n-(i-j)+1],b[i])*200);
            }
        }
        int ans=-INF;
        for (int i=0;i<=n;i++)
            ans=max(ans,f[n][i]);
        cout<<ans<<endl;
        scanf("%d",&n);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值