BZOJ 2437: [Noi2011]兔兔与蛋蛋

2437: [Noi2011]兔兔与蛋蛋

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 678  Solved: 429
[Submit][Status][Discuss]

Description

Input

输入的第一行包含两个正整数 n、m。 
接下来 n行描述初始棋盘。其中第i 行包含 m个字符,每个字符都是大写英文字母"X"、大写英文字母"O"或点号"."之一,分别表示对应的棋盘格中有黑色棋子、有白色棋子和没有棋子。其中点号"."恰好出现一次。 
接下来一行包含一个整数 k(1≤k≤1000) ,表示兔兔和蛋蛋各进行了k次操作。 
接下来 2k行描述一局游戏的过程。其中第 2i – 1行是兔兔的第 i 次操作(编号为i的操作) ,第2i行是蛋蛋的第i次操作。每个操作使用两个整数x,y来描述,表示将第x行第y列中的棋子移进空格中。 
输入保证整个棋盘中只有一个格子没有棋子, 游戏过程中兔兔和蛋蛋的每个操作都是合法的,且最后蛋蛋获胜。

Output

输出文件的第一行包含一个整数r,表示兔兔犯错误的总次数。 
接下来r 行按递增的顺序给出兔兔“犯错误”的操作编号。其中第 i 行包含一个整数ai表示兔兔第i 个犯错误的操作是他在游戏中的第 ai次操作。 
1 ≤n≤ 40, 1 ≤m≤ 40

Sample Input

样例一:
1 6
XO.OXO
1
1 2
1 1
样例二:
3 3
XOX
O.O
XOX
4
2 3
1 3
1 2
1 1
2 1
3 1
3 2
3 3
样例三:
4 4
OOXX
OXXO
OO.O
XXXO
2
3 2
2 2
1 2
1 3

Sample Output

样例一:
1
1
样例二:
0
样例三:
2
1
2

样例1对应图一中的游戏过程
样例2对应图三中的游戏过程

HINT

 

 

Source

分析:

和BZOJ 1443是一样的...

把空格看成黑点,然后就转化成了BZOJ 1443...

如果决策错误就代表从一个必胜态转移到了另一个必胜态,然后做完一个决策就把前一次空格所在位置的点删去,不断寻找最大匹配...

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;

const int maxn=40+5,maxm=1600+5,maxk=1000+5;

int hd[maxm],to[maxm<<1],nxt[maxm<<1];
int n,m,k,cnt,tot,f[maxn][maxn],co[maxm],mv[2][2]={0,-1,-1,0};
int c,ans,stx,sty,sta,is[maxm],pre[maxm],vis[maxm],del[maxm],res[maxk<<1];

char mp[maxn][maxn];

inline bool judge(char x){
	if(x=='X'||x=='.')
		return 1;
	return 0;
}

inline void add(int x,int y){
	to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
}

inline bool dfs(int x){
	if(del[x])
		return false;
	for(int i=hd[x];i!=-1;i=nxt[i])
		if(!vis[to[i]]&&!del[to[i]]){
			vis[to[i]]=1;
			if(pre[to[i]]==-1||dfs(pre[to[i]]))
				return pre[x]=to[i],pre[to[i]]=x,true;
		}
	return false;
}

signed main(void){
//	freopen("out.txt","w",stdout);
	scanf("%d%d",&n,&m);
	memset(hd,-1,sizeof(hd));
	memset(pre,-1,sizeof(pre));
	for(int i=1;i<=n;i++){
		scanf("%s",mp[i]+1);
		for(int j=1;j<=m;j++)
			if(mp[i][j]=='.')
				c=((i^j)&1)^1,stx=i,sty=j;
	}
	scanf("%d",&k);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			f[i][j]=++tot;co[f[i][j]]=((i^j)&1)^c;is[tot]=1;
			if(co[f[i][j]]==judge(mp[i][j]))
				for(int t=0;t<2;t++){
					int x=i+mv[t][0],y=j+mv[t][1];
					if(f[x][y])
						add(f[i][j],f[x][y]),add(f[x][y],f[i][j]);
				}
			else
				f[i][j]=0,is[tot]=0;
		}
	for(int i=1;i<=tot;i++)
		if(is[i]&&co[i])
			memset(vis,0,sizeof(vis)),dfs(i);
	for(int i=1;i<=k<<1;i++){
		int x=f[stx][sty],y=pre[x];del[x]=1;
		if(y!=-1){
			pre[x]=pre[y]=-1;
			memset(vis,0,sizeof(vis));
			if(!dfs(y))
				res[i]=1;
			else
				res[i]=0;
		}
		else
			res[i]=0;
		scanf("%d%d",&stx,&sty);
	}
	for(int i=1;i<=k<<1;i+=2)
		if(res[i]&&res[i+1])
			ans++;
	printf("%d\n",ans);
	for(int i=1;i<=k<<1;i+=2)
		if(res[i]&&res[i+1])
			printf("%d\n",(i+1)>>1);
	return 0;
}

  


By NeighThorn

posted @ 2017-03-06 13:20  NeighThorn  阅读(343)  评论(0编辑  收藏  举报