| 记录编号 |
97093 |
评测结果 |
AAAAWAAWAWWWWWW |
| 题目名称 |
1597.[USACO Dec08] 跳棋获胜 |
最终得分 |
46 |
| 用户昵称 |
cstdio |
是否通过 |
未通过 |
| 代码语言 |
C++ |
运行时间 |
0.047 s |
| 提交时间 |
2014-04-16 21:27:59 |
内存使用 |
1.11 MiB |
显示代码纯文本
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include<cstring>
using namespace std;
#define E (-1)
#define U (0)
#define O (1)
#define K (2)
//empty, unoccupied, opponent, king
char c;
int opp=0,vp;
int N;
int arr[205][205];
int vi[70000];
int vj[70000];
bool used[205][205];
int epos[205][205];
int dr[4] = {2,2,-2,-2};
int dc[4] = {2,-2,2,-2};
void rec(int i,int j){
while(epos[i][j]<4){ //while we still have unused edges at this vertex
if(i+dr[epos[i][j]]<0) epos[i][j]++; //if this edge takes us out of bounds, skip it
else if(i+dr[epos[i][j]]>=N) epos[i][j]++;
else if(j+dc[epos[i][j]]<0) epos[i][j]++;
else if(j+dc[epos[i][j]]>=N) epos[i][j]++;
else if(arr[i+dr[epos[i][j]]/2][j+dc[epos[i][j]]/2]!=O) epos[i][j]++; //if the square underneath this edge isn't an opposing piece, skip it
else if(arr[i+dr[epos[i][j]]][j+dc[epos[i][j]]]!=U) epos[i][j]++; //if the square on the other side of this edge is occupied, skip it
else if(epos[i+dr[epos[i][j]]][j+dc[epos[i][j]]]>3-epos[i][j]) epos[i][j]++;
//if we have already traversed this edge in the other direction, skip it
else {
epos[i][j]++; //delete this edge and then recurse on it
rec(i+dr[epos[i][j]-1],j+dc[epos[i][j]-1]);
}
}
vi[vp]=i; vj[vp]=j; vp++; //add this vertex to the path
}
bool sanitize(){
for(int s=0;s<vp-1;s++){
if(abs(vi[s+1]-vi[s])!=2) return 0; //check to see that the two adjacent vertices in the path are connected by an edge
if(abs(vj[s+1]-vj[s])!=2) return 0;
if(arr[(vi[s+1]+vi[s])/2][(vj[s+1]+vj[s])/2]!=O) return 0; //check to see that the square underneath the edge has an opposing piece
}
return 1;
}
int euler(int si,int sj){
for(int i=0;i<N;i++){
memset(used[i],0,sizeof(used[i]));
memset(epos[i],0,sizeof(epos[i]));
}
vp = 0;
arr[si][sj]=U; //set the starting square to be unoccupied
rec(si,sj); //run Eulerian path algorithm
arr[si][sj]=K; //put the king back down in the starting square
if(!sanitize()) return -1; //if the path is invalid, return -1
return vp; //otherwise, return the number of edges in the path
}
int main(){
FILE *fin = fopen("winchk.in","r");
FILE *fout = fopen("winchk.out","w");
fscanf(fin,"%d",&N);
for(int i=0;i<N;i++)
for(int j=0;j<N;j++){
do fscanf(fin,"%c",&c); while(c==' '||c=='\n');
if(c=='-') arr[i][j]=E;
if(c=='+') arr[i][j]=U;
if(c=='o') { arr[i][j]=O; opp++; }
if(c=='K') arr[i][j]=K;
}
int cnte = 0, cnto = 0;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<4;k++)
if(arr[i][j]==K&&i+dr[k]/2>=0&&i+dr[k]/2<N&&j+dc[k]/2>=0&&j+dc[k]/2<N&&arr[i+dr[k]/2][j+dc[k]/2]==O){
//check how many kings of each parity touch an edge
if((i+j)%4==1) cnto++;
else cnte++;
break;
}
for(int i=0;i<N;i++)
for(int j=0;j<N;j++){
if(cnto!=1&&(i+j)%4==1) continue; //if more than one king of this parity touches an edge, we can't find a solution for this parity
if(cnte!=1&&(i+j)%4==3) continue;
if(arr[i][j]==K&&euler(i,j)==opp+1){ //check for a path from each king
for(int k=vp-1;k>=0;k--) //print the path if it exists
fprintf(fout,"%d %d\n",vi[k]+1,vj[k]+1);
fclose(fin); fclose(fout); return 0;
}
}
fprintf(fout,"impossible\n");
fclose(fin); fclose(fout);
return 0;
}