[NOI2011]兔兔与蛋蛋游戏
2018-01-04 20:32
393 查看
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
[b]想看详细的图和分析,可以参考https://www.cnblogs.com/maijing/p/4703094.html[/b]
[b]我们可以把这个过程看成两人对网格图进行黑白染色,变成了一个二分图模型,即当前位置向相邻不同颜色的位置连边,构成的二分图,一次游戏相当于一个最大匹配.[/b]
[b]最重要的一个结论:如果一定存在包含当前位置的最大匹配,那么处于先手必胜状态
证明:[/b]
[b]因为当前点不处于最大匹配中,那么只有非匹配边可以走,假设走到了\(v\),\(v\)点则可以走匹配边,假设走了一条匹配边,则到达的下一个点只能走非匹配边,因为匹配的点是\(v\), 综上:先手只能一直沿着非匹配边走,而后手有匹配边可以走,所以不是必胜状态[/b]
[b]所以只需要判断一个点是否在一定在最大匹配中了[/b]
[b]
方法是:删除该点,再跑一次最大匹配,如果能成功匹配则不满足条件.[/b]
[b]一个细节:一定不会存在回路,即一个点只会走一次,所以走过的点不能再进入匹配中[/b]
[b]转载自http://www.cnblogs.com/Yuzao/p/8146313.html[/b]
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; struct Node { int next,to; }edge[50001]; int head[2001],num,n,m,x,y,a[101][101],id[101][101],cnt,cx[2001],ban[2001],k,ans[1001],tot; bool vis[2001],b1,b2; void add(int u,int v) { num++; edge[num].next=head[u]; head[u]=num; edge[num].to=v; num++; edge[num].next=head[v]; head[v]=num; edge[num].to=u; } void build() {int i,j; for (i=1;i<=n;i++) { for (j=1;j<=m;j++) if (((i+j)&1)^((x+y)&1)^(a[i][j]==1)) id[i][j]=++cnt; } for (i=1;i<=n;i++) { for (j=1;j<=m;j++) if (id[i][j]) { if (i>1&&id[i-1][j]) add(id[i][j],id[i-1][j]); if (i<n&&id[i+1][j]) add(id[i][j],id[i+1][j]); if (j>1&&id[i][j-1]) add(id[i][j],id[i][j-1]); if (j<m&&id[i][j+1]) add(id[i][j],id[i][j+1]); } } } bool dfs(int x) {int i; for (i=head[x];i;i=edge[i].next) { int v=edge[i].to; if (vis[v]==0&&ban[v]==0) { vis[v]=1; if (!cx[v]||dfs(cx[v])) { cx[x]=v;cx[v]=x; return 1; } } } return 0; } int main() {int i,j,u,v; char s[101]; cin>>n>>m; for (i=1;i<=n;i++) { scanf("%s",s+1); for (j=1;j<=m;j++) { if (s[j]=='O') a[i][j]=0; else if (s[j]=='X') a[i][j]=1; else if (s[j]=='.') x=i,y=j,a[i][j]=1; } } build(); for (i=1;i<=n;i++) { for (j=1;j<=m;j++) if (id[i][j]) { if (!cx[id[i][j]]) { memset(vis,0,sizeof(vis)); dfs(id[i][j]); } } } cin>>k; for (i=1;i<=k;i++) { u=id[x][y]; ban[u]=1; if (cx[u]) { v=cx[u]; cx[u]=cx[v]=0; memset(vis,0,sizeof(vis)); b1=(!dfs(v)); } else b1=0; scanf("%d%d",&x,&y); u=id[x][y]; ban[u]=1; if (cx[u]) { v=cx[u]; cx[u]=cx[v]=0; memset(vis,0,sizeof(vis)); b2=(!dfs(v)); } else b2=0; if (b1&&b2) ans[++tot]=i; scanf("%d%d",&x,&y); } cout<<tot<<endl; for (i=1;i<=tot;i++) printf("%d\n",ans[i]); }
相关文章推荐
- NOI2011 兔兔与蛋蛋游戏
- ★【二分图匹配】【博弈论】【NOI2011】兔兔和蛋蛋的游戏
- 【LOJ】#2447. 「NOI2011」兔兔与蛋蛋的游戏
- 【博弈+二分图匹配】[NOI2011]兔兔与蛋蛋游戏
- [二分图博弈] BZOJ 1443 [JSOI2009]游戏Game & BZOJ 2437 [Noi2011]兔兔与蛋蛋
- bzoj2437 [Noi2011]兔兔与蛋蛋
- bzoj 2437 [Noi2011]兔兔与蛋蛋 [二分图匹配]
- bzoj2437 [Noi2011]兔兔与蛋蛋
- BZOJ2437: [Noi2011]兔兔与蛋蛋
- bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势
- BZOJ2437 [Noi2011]兔兔与蛋蛋 【博弈论 + 二分图匹配】
- BZOJ2437 NOI2011兔兔与蛋蛋(二分图匹配+博弈)
- bzoj 2437: [Noi2011]兔兔与蛋蛋
- [BZOJ 2437][NOI 2011]兔兔与蛋蛋(二分图匹配)
- bzoj 2437: [Noi2011]兔兔与蛋蛋 (二分图博弈+dinic)
- 2437: [Noi2011]兔兔与蛋蛋 - BZOJ
- [BZOJ]2437: [Noi2011]兔兔与蛋蛋 二分图匹配+博弈
- 【bzoj2437】【NOI2011】【兔兔与蛋蛋】【二分图博弈】
- bzoj 2437: [Noi2011]兔兔与蛋蛋 博弈论+二分图匹配
- BZOJ 2437: [Noi2011]兔兔与蛋蛋