隔膜
题面
小 l 和小 c 在玩游戏。
她们发明了一个新的游戏。
有一个 n × n 的棋盘,初始有些地方有棋子。
每次行动时,需要在棋盘上找到一个 k × k 的正方形,使得上面没有任何一个棋子。如果无法找
到,则她就输掉了这个游戏。
然后,她需要在棋盘任. 意. 一. 个. 没有棋子的地方放上一个棋子,不需要保证这个棋子在 k × k 的正方形中。
小 c 先手,问谁有必胜策略。
输入格式
从文件 lcyrcx.in 中读入数据。
第一行包含两个正整数 n, k。
接下来 n 行,每行输入一个长度为 n 的 0/1 字符串,1 表示上面初始有棋子,0 表示上面初始
没有棋子。
输出格式
输出到文件 lcyrcx.out 中。
输出一行一个字符串,表示谁赢了。如果小 l 赢了,输出 yc,否则输出 rx。
题解
讨论3种情况:
1.一开始棋盘上找不到正方形。此时答案即为小l赢了
2.一开始棋盘找得到正方形且上存在一个点,使得在这个点放了一个棋子后棋盘上找不到正方形,此时小c先手放在这个位置,小l就找不到位置放了,此时答案即为小c赢了。
3.除去1,2种情况即为3情况,此时图上一定能找到至少2个互不相交的正方形。当只剩2个互不相交的正方形时,谁先往其中一个正方形里放棋子,谁就输了。所以此时最优决策就是把不在互不相交正方形内的空位置全都放满。然后放完之后必须放在正方形内的那个人就输了。
若存在3个及以上个互不相交的正方形,可以证明,先放正方形内和先放正方形外的空位置到最后只剩下2个互不相交的正方形时的人是一样的。证明:若先放正方形内,能找到的正方形便减1,而此时若只剩2个,便不能再放正方形内。若先放正方形外,到最后就会剩下一堆互不相交的正方形,然后又回到了上面的情况。
所以,情况3的答案ans=空格子的总数-2kk,若ans为奇数,则小c赢了,否则小l赢了。
代码如下
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int k=0,f=1;char ch;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')k=k*10+ch-'0',ch=getchar();
return k*f;
}
const int N=1e3+5;
int n,k,a[N][N];
void point1(){
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(a[i][j]){printf("yc\n");return;}
printf("rx\n");
}
int hang[N][N],lie[N][N],f[N][N],s[N][N],cnt_,sum;
bool solve(){
for(int i=1;i<=n;++i){
for(int j=1,cnt=0;j<=n;++j){
if(j>k&&a[i][j-k])cnt--;
if(a[i][j])cnt++;
if(j>=k)hang[i][j-k+1]=cnt;//,cout<<i<<" "<<j-k+1<<" "<<cnt<<endl;
}
/*for(int j=1,cnt=0;j<=n;++j){
if(j>k&&a[j-k][i])cnt--;
if(a[j][i])cnt++;
if(j>=k)lie[j-k+1][i]=cnt;
}*/
}
for(int i=1;i+k-1<=n;++i){
for(int j=1,cnt=0;j<=n;++j){
if(j>k)cnt-=hang[j-k][i];
cnt+=hang[j][i];
if(j>=k&&!cnt){
f[j+1][i]--;
f[j-k+1][i]++;
f[j-k+1][i+k]--;
f[j+1][i+k]++;
cnt_++;
}
}
}
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+f[i][j];//,cout<<i<<" "<<j<<" "<<s[i][j]<<endl;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j){
if(s[i][j]==cnt_)return false;
}
return true;
}
int main()
{
char ch;
// freopen("lcyrcx.in","r",stdin);
// freopen("lcyrcx.out","w",stdout);
n=read(),k=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
cin>>ch,a[i][j]=ch-'0',sum+=(a[i][j]^1);
//cout<<sum<<endl;
if(solve()){
// cout<<"FAQ "<<cnt_<<endl;
if((sum-2*k*k)%2)printf("rx\n");
else printf("yc\n");
}
else{
if(cnt_==0)printf("yc\n");
else printf("rx\n");
}
return 0;
}
/*
4 2
0001
0000
1100
1111
*/