会做jsoi那道game,这题就非常简单了吧

我们考虑空格的移动,显然,初始与空格位置距离为奇数的黑棋和距离为偶数的白棋并没有什么用,

空格不会移到那,我们直接把他们当作障碍,其他点我们当作可移动区域

这不就和game那道题一样了吗,只不过这题不问棋子放哪

而是给定棋子位置,问当前是否是先手必胜

(错误操作就是指当前是先手必胜而移动一格还是先手必胜的操作)

我们对图重新黑白染色,做二分图匹配,显然,棋子在一定能被匹配的点上时,是先手必胜

证明类似game,因为棋子在一定在一定能被匹配的点上,我们第一步走向匹配点

下一步对方要么不能走,要么走一条非匹配边,那所到达的点,一定是匹配了的

否则,一开始的点就不一定在匹配,与假设矛盾,所以最后走的一条边一定是匹配边得证

至于怎么找一定能被匹配的点,我们做完二分图匹配后,如果这个点匹配了,那么我们删掉这个点,从这个点配对的点出发看是否能找到增广路即可

  1 const dx:array[1..4] of longint=(0,0,1,-1);
  2       dy:array[1..4] of longint=(1,-1,0,0);
  3 
  4 type node=record
  5        po,next:longint;
  6      end;
  7 
  8 var e:array[0..4010] of node;
  9     v:array[0..2010] of boolean;
 10     b:array[0..50,0..50] of longint;
 11     a:array[0..50,0..50] of char;
 12     mat,p,c:array[0..2010] of longint;
 13     t,xx,yy,i,n,m,j,k,len,x,y,ans:longint;
 14     f1,f2:boolean;
 15 
 16 procedure add(x,y:longint);
 17   begin
 18     inc(len);
 19     e[len].po:=y;
 20     e[len].next:=p[x];
 21     p[x]:=len;
 22   end;
 23 
 24 function dfs(x:longint):boolean;
 25   var i,y:longint;
 26   begin
 27     v[x]:=true;
 28     i:=p[x];
 29     while i<>0 do
 30     begin
 31       y:=e[i].po;
 32       if not v[y] and (mat[y]<>-1) then
 33       begin
 34         v[y]:=true;
 35         if (mat[y]=0) or dfs(mat[y]) then
 36         begin
 37           mat[y]:=x;
 38           mat[x]:=y;
 39           exit(true);
 40         end;
 41       end;
 42       i:=e[i].next;
 43     end;
 44     exit(false);
 45   end;
 46 
 47 function check:boolean;
 48   var j,k:longint;
 49   begin
 50     k:=b[x,y];
 51     j:=mat[k];
 52     mat[j]:=0;
 53     mat[k]:=-1;
 54     if j=0 then exit(false)
 55     else begin
 56       fillchar(v,sizeof(v),false);
 57       exit(not dfs(j));
 58     end;
 59   end;
 60 
 61 begin
 62   readln(n,m);
 63   for i:=1 to n do
 64   begin
 65     for j:=1 to m do
 66     begin
 67       read(a[i,j]);
 68       if a[i,j]='.' then
 69       begin
 70         x:=i;
 71         y:=j;
 72         a[i,j]:='X';
 73       end;
 74     end;
 75     readln;
 76   end;
 77   for i:=1 to n do
 78     for j:=1 to m do
 79       if (a[i,j]='O') xor ((abs(i-x)+abs(j-y)) mod 2=0) then
 80       begin
 81         inc(t);
 82         b[i,j]:=t;
 83       end;
 84 
 85   for i:=1 to n do
 86     for j:=1 to m do
 87       if b[i,j]>0 then
 88       begin
 89         for k:=1 to 4 do
 90         begin
 91           xx:=i+dx[k];
 92           yy:=j+dy[k];
 93           if b[xx,yy]>0 then add(b[i,j],b[xx,yy]);
 94         end;
 95       end;
 96 
 97   for i:=1 to t do
 98     if mat[i]=0 then
 99     begin
100       fillchar(v,sizeof(v),false);
101       dfs(i);
102     end;
103     
104   readln(k);
105   for i:=1 to k do
106   begin
107     f1:=check;
108     readln(x,y);
109     f2:=check;
110     if f1 and f2 then
111     begin
112       inc(ans);
113       c[ans]:=i;
114     end;
115     readln(x,y);
116   end;
117   writeln(ans);
118   for i:=1 to ans do
119     writeln(c[i]);
120 end.
View Code

 

posted on 2015-06-30 16:03  acphile  阅读(302)  评论(0编辑  收藏  举报