记录编号 62117 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2011]兔兔与蛋蛋游戏 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.010 s
提交时间 2013-06-19 21:40:36 内存使用 0.35 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<deque>
#include<iomanip>
#include<cstring>
#include<stack>
#include<vector>
#include<queue>
#include<fstream>
using namespace std;
const int SIZEN=50,SIZEG=1700;
int n,m;//棋盘大小
int K;
int N;//图的大小(总点数)
char board[SIZEN][SIZEN]={0};
//点(x,y)的序号:x*m+y,其中x,y>=0
vector<int> c[SIZEG];//邻接表
bool visit[SIZEG]={0};
int match[SIZEG]={0};
bool une[SIZEG]={0};
class POINT{
public:
	int x,y;
}space;
bool findpath(int x){
	if(visit[x]||une[x]) return false;
	int i,v;
	for(i=0;i<c[x].size();i++){
		v=c[x][i];
		if(visit[v]||une[v]) continue;
		visit[v]=true;
		if(match[v]==-1||findpath(match[v])){
			match[v]=x;
			match[x]=v;
			return true;
		}
	}
	return false;
}
int hung(void){
	int i,ans=0;
	for(i=0;i<N;i++) if(findpath(i)) ans++;
	return ans;
}
deque<int> wrong;
void write(void){
	printf("%d\n",wrong.size());
	if(wrong.empty()) return;
	int i;
	for(i=0;i<wrong.size();i++) printf("%d\n",wrong[i]);
	printf("\n");
}
int getid(int x,int y){
	return x*m+y;
}
void del(POINT space){
	int now=getid(space.x,space.y);
	une[now]=true;
}
void res(POINT space){
	int now=getid(space.x,space.y);
	une[now]=false;
}
bool swin(bool rabbit,int step,POINT loc){
	POINT op;
	del(loc);
	scanf("%d%d",&op.x,&op.y);
	op.x--,op.y--;
	bool flag;
	if(step==2*K){
		res(loc);
		memset(visit,0,sizeof(visit));
		hung();
		return true;
	}
	flag=swin(!rabbit,step+1,op);
	res(loc);
	memset(visit,0,sizeof(visit));
	if(findpath(getid(loc.x,loc.y))){
		if(rabbit&&flag) wrong.push_front((step+1)/2);
		return true;
	}
	return false;
}
queue<POINT> Q;
void addedge(int x,int y){
	c[x].push_back(y);
}
void BFS(void){//这个BFS其实可以用更为高♂雅的方式写的
	Q.push(space);
	visit[getid(space.x,space.y)]=false;
	POINT fr;
	int now,nx,ny,temp;
	while(!Q.empty()){
		fr=Q.front();Q.pop();
		nx=fr.x,ny=fr.y;
		now=getid(nx,ny);
		char ch=board[nx][ny];
		if(nx<n-1&&board[nx+1][ny]!=ch){
			temp=getid(nx+1,ny);
			addedge(now,temp);
			if(visit[temp]){
				visit[temp]=false;
				Q.push((POINT){nx+1,ny});
			}
		}
		if(nx>0&&board[nx-1][ny]!=ch){
			temp=getid(nx-1,ny);
			addedge(now,temp);
			if(visit[temp]){
				visit[temp]=false;
				Q.push((POINT){nx-1,ny});
			}
		}
		if(ny<m-1&&board[nx][ny+1]!=ch){
			temp=getid(nx,ny+1);
			addedge(now,temp);
			if(visit[temp]){
				visit[temp]=false;
				Q.push((POINT){nx,ny+1});
			}
		}
		if(ny>0&&board[nx][ny-1]!=ch){
			temp=getid(nx,ny-1);
			addedge(now,temp);
			if(visit[temp]){
				visit[temp]=false;
				Q.push((POINT){nx,ny-1});
			}
		}
	}
}
void read(void){
	scanf("%d%d",&n,&m);
	N=n*m;
	int i,j;
	for(i=0;i<n;i++){
		getchar();
		for(j=0;j<m;j++){
			scanf("%c",&board[i][j]);
			if(board[i][j]=='.'){
				space.x=i;
				space.y=j;
				board[i][j]='X';
			}
		}
	}
	scanf("%d",&K);
	memset(visit,1,sizeof(visit));
	memset(match,-1,sizeof(match));
	memset(une,0,sizeof(une));
}
int main(){
	freopen("noi2011_game.in","r",stdin);
	freopen("noi2011_game.out","w",stdout);
	read();
	BFS();
	swin(true,1,space);
	write();
	return 0;
}
//若起点不在某个最大匹配中,先手必败
//若起点在所有最大匹配中,先手必胜