扑克游戏

来源:互联网 发布:淘宝 处方药购买流程 编辑:程序博客网 时间:2024/05/17 08:27

题目描述 Problem Description

著名的阳姐•查兰•伊丽莎白一世因为治理国家太有方了, 最近国泰民安, 阳姐就只能和大黄或者小昊开始玩扑克游戏了。
这个扑克游戏的规则是这样的。 首先, 弄出 NN 保证为偶数) 张牌(当我没说扑克吧), 每张牌上都有一个分数 Wi, 抽到这张牌的人将得到 Wi 的分数。将这 N 张牌按照顺序叠成一叠。 两个人轮流抽牌, 每次都只能抽现存的最上面的牌或者最下面的牌, 并且不放回。 当牌堆被抽光的时候, 分数最高的人胜利。因为女士优先, 每次都是阳姐先抽。 阳姐现在想知道, 自己能不能赢, 最多能得到多少分, 自 己得到最高分的时候会抽到原牌堆中的哪些牌。(当两种抽法得到的分数相等时, 优先取最上面那张牌) 这样说可能会有些不敬, 不过由于阳姐出色的(调) 教(揉) 练, 小昊和大黄的智商可以视为极高, 也就是说, 双方都会执行对自己最有利的抽法。


输入描述 Input Description

输入第一行一个正整数 N, 代表牌堆中牌的个数。
第二行顺次包含 N 个数, 代表牌堆中最上面的牌一直到最下面的牌的分数。


输出描述 Output Description

输出第一行为“WIN ” 或“ LOSE ”, 代表赢或者输。
输出第二行代表阳姐最高的得分。
输出第三行 N2 个正整数, 代表阳姐得到最高得分的时候, 按她抽到的先后顺序, 输出她抽到的牌在原来牌堆中的序号。


输入样例 Sample Input

10
8 4 1 6 3 1 9 7 6 6


输出样例 Sample Output

WIN
28
1 10 8 6 4


分析 I Think

对于区间 [i,j] 内的牌,先取的人能得到的最大得分是确定的,所以记 fi,j 表示区间 [i,j] 的牌的得分的最大值, si,j 表示区间 [i,j] 内的牌的得分和,因为可以取最前面或最后面的,所以 wi,j=si,jmin{wi+1,j+wi,j1}


代码 Code

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int id[] = {-1,1};const int Size = 1010;int n;int f[Size][Size];int s[Size][Size];int sum;void display(int,int,bool);int main(){    scanf("%d",&n);    for(int i=1;i<=n;++i)        scanf("%d",&s[i][i]);    for(int i=n-1;i>=1;--i)        for(int j=i+1;j<=n;++j)            s[i][j] = s[i][j-1]+s[j][j];    for(int i=1;i<=n;++i)        f[i][i] = s[i][i];    for(int i=n-1;i>=1;--i)        for(int j=i+1;j<=n;++j)            f[i][j] = s[i][j]-min(f[i+1][j],f[i][j-1]);    if(sum-f[1][n] > f[1][n])        printf("LOSE\n%d\n",f[1][n]);    else        printf("WIN\n%d\n",f[1][n]);    display(1,n,true);    return 0;}void display(int x,int y,bool flag){    if(x > y)        return ;    if(s[x][y]-f[x+1][y] == f[x][y]){        if(flag)            printf("%d ",x);        display(x+1,y,!flag);    }    else{        if(flag)            printf("%d ",y);        display(x,y-1,!flag);    }}
0 0