• [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

    想看详细的图和分析,可以参考https://www.cnblogs.com/maijing/p/4703094.html

    我们可以把这个过程看成两人对网格图进行黑白染色,变成了一个二分图模型,即当前位置向相邻不同颜色的位置连边,构成的二分图,一次游戏相当于一个最大匹配.

    最重要的一个结论:如果一定存在包含当前位置的最大匹配,那么处于先手必胜状态
    证明:

    因为当前点不处于最大匹配中,那么只有非匹配边可以走,假设走到了(v),(v)点则可以走匹配边,假设走了一条匹配边,则到达的下一个点只能走非匹配边,因为匹配的点是(v), 综上:先手只能一直沿着非匹配边走,而后手有匹配边可以走,所以不是必胜状态

    所以只需要判断一个点是否在一定在最大匹配中了
    方法是:删除该点,再跑一次最大匹配,如果能成功匹配则不满足条件.

    一个细节:一定不会存在回路,即一个点只会走一次,所以走过的点不能再进入匹配中

    转载自http://www.cnblogs.com/Yuzao/p/8146313.html

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 struct Node
      8 {
      9   int next,to;
     10 }edge[50001];
     11 int head[2001],num,n,m,x,y,a[101][101],id[101][101],cnt,cx[2001],ban[2001],k,ans[1001],tot;
     12 bool vis[2001],b1,b2;
     13 void add(int u,int v)
     14 {
     15   num++;
     16   edge[num].next=head[u];
     17   head[u]=num;
     18   edge[num].to=v;
     19   num++;
     20   edge[num].next=head[v];
     21   head[v]=num;
     22   edge[num].to=u;
     23 }
     24 void build()
     25 {int i,j;
     26   for (i=1;i<=n;i++)
     27     {
     28       for (j=1;j<=m;j++)
     29     if (((i+j)&1)^((x+y)&1)^(a[i][j]==1))
     30       id[i][j]=++cnt;
     31     }
     32   for (i=1;i<=n;i++)
     33     {
     34       for (j=1;j<=m;j++)
     35     if (id[i][j])
     36       {
     37         if (i>1&&id[i-1][j])
     38           add(id[i][j],id[i-1][j]);
     39         if (i<n&&id[i+1][j])
     40           add(id[i][j],id[i+1][j]);
     41         if (j>1&&id[i][j-1])
     42           add(id[i][j],id[i][j-1]);
     43         if (j<m&&id[i][j+1])
     44           add(id[i][j],id[i][j+1]);
     45       }
     46     }
     47 }
     48 bool dfs(int x)
     49 {int i;
     50   for (i=head[x];i;i=edge[i].next)
     51     {
     52       int v=edge[i].to;
     53       if (vis[v]==0&&ban[v]==0)
     54     {
     55       vis[v]=1;
     56       if (!cx[v]||dfs(cx[v]))
     57         {
     58           cx[x]=v;cx[v]=x;
     59           return 1;
     60         }
     61     }
     62     }
     63   return 0;
     64 }
     65 int main()
     66 {int i,j,u,v;
     67   char s[101];
     68   cin>>n>>m;
     69   for (i=1;i<=n;i++)
     70     {
     71       scanf("%s",s+1);
     72       for (j=1;j<=m;j++)
     73     {
     74       if (s[j]=='O') a[i][j]=0;
     75       else if (s[j]=='X') a[i][j]=1;
     76       else if (s[j]=='.') x=i,y=j,a[i][j]=1;
     77     }
     78     }
     79   build();
     80   for (i=1;i<=n;i++)
     81     {
     82       for (j=1;j<=m;j++)
     83     if (id[i][j])
     84       {
     85         if (!cx[id[i][j]])
     86           {
     87         memset(vis,0,sizeof(vis));
     88         dfs(id[i][j]);
     89           }
     90       }
     91     }
     92   cin>>k;
     93   for (i=1;i<=k;i++)
     94     {
     95       u=id[x][y];
     96       ban[u]=1;
     97       if (cx[u])
     98     {
     99       v=cx[u];
    100       cx[u]=cx[v]=0;
    101       memset(vis,0,sizeof(vis));
    102       b1=(!dfs(v));
    103     }
    104       else b1=0;
    105       scanf("%d%d",&x,&y);
    106       u=id[x][y];
    107       ban[u]=1;
    108       if (cx[u])
    109     {
    110       v=cx[u];
    111       cx[u]=cx[v]=0;
    112       memset(vis,0,sizeof(vis));
    113       b2=(!dfs(v));
    114     }
    115       else b2=0;
    116       if (b1&&b2)
    117     ans[++tot]=i;
    118       scanf("%d%d",&x,&y);
    119     }
    120   cout<<tot<<endl;
    121   for (i=1;i<=tot;i++)
    122     printf("%d
    ",ans[i]);
    123 }
  • 相关阅读:
    软件设计中的分层模式, 三层开发遵循的原则,分层开发的特点和优势
    什么是jsp?
    在Servlet中如何如何获取请求的参数?
    Servlet的加载(执行过程,原理)和生命周期
    servlet的注册
    什么是servlet容器
    什么是Servlet
    如何访问动态页面——URL
    什么是C/S? Client/server的简写,这里Server指的是DBServer。
    MVC(Model-View-Controller)软件设计模式
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8195754.html
Copyright © 2020-2023  润新知