zoukankan      html  css  js  c++  java
  • 2437: [Noi2011]兔兔与蛋蛋

    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

    神题,竟然是二分图匹配,看了题解才知道

    因为走的路线黑白交替所以我们考虑二分图匹配,相邻的黑白连边(空格一开始视为黑色)

    然后可以发现走的路线是一条交错轨,那么必胜的条件是起点一定在最大匹配中

    如果在的话,那么我们每次都走匹配边,最后没有路的一定是后手(可以画图yy一下,交错轨走到最后一定是一条匹配边,要不然起点就不一定在最大匹配中了)

    如果起点不一定在最大匹配中那么,起点连的点都一定在最大匹配中(在去掉起点之后)(可以用反证法)

     1 const  
     2     maxn=42;
     3     maxk=1010;
     4 var
     5     p,a:array[0..maxn,0..maxn]of longint;
     6     first,last,next:array[0..maxn*maxn*20]of longint;
     7     link:array[0..maxn*maxn]of longint;
     8     vis:array[0..maxn*maxn]of boolean;
     9     ans:array[0..maxk]of longint;
    10     n,m,k,tot,cnt,xi,yi:longint;
    11  
    12 procedure insert(x,y:longint);
    13 begin
    14     inc(tot);last[tot]:=y;next[tot]:=first[x];first[x]:=tot;
    15     inc(tot);last[tot]:=x;next[tot]:=first[y];first[y]:=tot;
    16 end;
    17  
    18 function find(x:longint):boolean;
    19 var
    20     i:longint;
    21 begin
    22     if x<0 then exit(false);
    23     i:=first[x];
    24     while i<>0 do
    25         begin
    26             if not vis[last[i]] then
    27             begin
    28                 vis[last[i]]:=true;
    29                 if (link[last[i]]=0) or (find(link[last[i]])) then
    30                 begin
    31                     link[x]:=last[i];
    32                     link[last[i]]:=x;
    33                     exit(true);
    34                 end;
    35             end;
    36             i:=next[i];
    37         end;
    38     exit(false);
    39 end;
    40  
    41 procedure main;
    42 var
    43     i,j,v:longint;
    44     c:char;
    45     flag1,flag2:boolean;
    46 begin
    47     read(n,m);
    48     for i:=1 to n do
    49         for j:=1 to m do
    50             begin
    51                 inc(cnt);p[i,j]:=cnt;
    52                 repeat
    53                     read(c);
    54                 until (c='X') or (c='O') or (c='.');
    55                 if c='.' then
    56                 begin
    57                     xi:=i;
    58                     yi:=j;
    59                 end;
    60                 if c<>'O' then a[i,j]:=1;
    61                 if (i>1) and (a[i,j]<>a[i-1,j]) then insert(p[i,j],p[i-1,j]);
    62                 if (j>1) and (a[i,j]<>a[i,j-1]) then insert(p[i,j],p[i,j-1]);
    63             end;
    64     for i:=1 to n do
    65         for j:=1 to m do
    66             if a[i,j]=0 then
    67             begin
    68                 fillchar(vis,sizeof(vis),false);
    69                 find(p[i,j]);
    70             end;
    71     read(k);cnt:=0;
    72     for i:=1 to k do
    73         begin
    74             v:=link[p[xi,yi]];link[v]:=0;
    75             link[p[xi,yi]]:=-1;
    76             fillchar(vis,sizeof(vis),false);
    77             if v=0 then flag1:=false
    78             else flag1:=not find(v);
    79             read(xi,yi);
    80             v:=link[p[xi,yi]];link[v]:=0;
    81             link[p[xi,yi]]:=-1;
    82             fillchar(vis,sizeof(vis),false);
    83             if v=0 then flag2:=false
    84             else flag2:=not find(v);
    85             read(xi,yi);
    86             if flag1 and flag2 then
    87             begin
    88                 inc(cnt);ans[cnt]:=i;
    89             end;
    90         end;
    91     writeln(cnt);
    92     for i:=1 to cnt do writeln(ans[i]);
    93 end;
    94  
    95 begin
    96     main;
    97 end.
    View Code
  • 相关阅读:
    HDU 1124 Factorial(简单数论)
    29.QT主窗口加widget
    28.开始画面和异形窗口
    27.Qt时钟
    26.QT颜色与布局
    25.QT进度条
    146.正则表达式
    24.qint64转QString 以及获取文件属性
    23.QFile遍历
    22.监视文件
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3803722.html
Copyright © 2011-2022 走看看