jzoj【NOIP2011模拟10.31】T1游戏

T1游戏

Description

Alice和Bob在玩一个游戏,游戏是在一个N*N的矩阵上进行的,每个格子上都有

一个正整数。当轮到Alice/Bob时,他/她可以选择最后一列或最后一行,并将其删除,但

必须保证选择的这一行或这一列所有数的和为偶数。如果他/她不能删除最后一行或最后一

列,那么他/她就输了。两人都用最优策略来玩游戏,Alice先手,问Alice是否可以必胜?

Input

第一行:T,表示数据组数

对于每组数据的第一行:N

接下来N行,每行N个数,描述这个矩阵

Output

如果Alice必胜输出W,否则输出L

一道dp题,
我们可以从右上角开始,逐一枚举{当最终点落在(i,j)上的输赢情况},
没有平局,所以只需要考虑是否为偶数和是否必胜,
于是就可以进行判断,
如果  当前列为偶数,且去除此列后的最右下角的点必输,那么这个点可以标记做必胜,
同理 当前行为偶数,同样判断取出后的情况即可。
用前缀和(sum)来优化。
当 sum[i][j]-sum[i][j-1])%2==0  dp[i][i]=max(dp[i][j-1]^1,dp[i][j]);
当 sum[i][j]-sum[i-1][j])%2==0  dp[i][i]=max(dp[i-1][j-1]^1,dp[i][j]);
于是
#include<bits/stdc++.h>
using namespace std;
bool dp[1005][1005];
int t,f[1005][1005],n;
int main()
{
    cin>>t;
    while(t--)
    {
        memset(f,0,sizeof(f));
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&f[i][j]);
            f[i][j]=f[i][j]+f[i-1][j]+f[i][j-1]-f[i-1][j-1]; 
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(dp[i][j-1]==false)
            if((f[i][j]-f[i][j-1])%2==0)
            {
                dp[i][j]=1;continue;
            }
            if(dp[i-1][j]==false)
            if((f[i][j]-f[i-1][j])%2==0)
            {
                dp[i][j]=1;continue;
            } 
        }
        if(dp[n][n])
        printf("W
");
        else
        printf("L
");
    }
}
 
原文地址:https://www.cnblogs.com/you-xiao-mang-ci/p/11285299.html