定義如下圖所示 所有1構成一個折角(對角線上的一點即它正上方和正左方的點) 則圖中一共有2*n+1個折角(N=2)
00100
00100
11100
00000
00000
每兩次改變可以改變一個矩形的四個角,以(1,1)爲左上角,將所有加號除第一行或和第一列外的位置全部變成減號,,如下圖
10110
10000
10000
00000
這時每個折角最多有兩個加號,改變有兩個加號的折角,使這個加號移到對角線上,這樣每個折角就最多就只剩一個了,
10010
10000
00100
00000
一共只有2*n+1個折角,加號的個數不會超過2n+1個
因爲每次更改都是更改偶數個(4個),所以加號個數的奇偶性不會改變,所以只要一開始是偶數個加號,那麼最後至多就只有2*n個
如果一開始是奇數,更改對角線使加號變成偶數個(對角線上有奇數個點,更改後必然更改加號個數奇偶性)
#include <cstdio>
#include <string>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
int n,ar[50][50],ans[50];
void initans(int r1,int r2,int c1,int c2){
ans[r1]=c1,ans[r2]=c2;
int t=1;
ar[r2][c2]=(ar[r2][c2]==1?0:1);
ar[r1][c1]=(ar[r1][c1]==1?0:1);
for(int i=1;i<=2*n+1;i++){
if(i==r1||i==r2)continue;
if(t==c1||t==c2)t++;
if(t==c1||t==c2)t++;
ans[i]=t;
t++;
}
}
void printans(){
for(int i=1;i<=2*n;i++)printf("%d ",ans[i]);
printf("%d\n",ans[2*n+1]);
}
/*
00100 定義如右圖所示 所有1構成一個折角 則圖中一共有2*n+1個折角(N=2)
00100 構造 使每個折角上只有一個加號
11100 每兩次改變可以改變一個矩形的四個角,以(1,1)爲左上角,將所有加號移到第一行或者第一列
00000 這時每個折角最多有兩個加號,同樣改變矩形頂角將這個加號移到對角線上,這樣每個折角就只剩一個了,
00000 因爲每次更改都是更改偶數個(4個),所以加號個數的奇偶性不會改變,所以只要一開始是偶數個加號,那麼最後至多就只有2*n個
如果一開始是奇數,更改對角線使加號變成偶數個(對角線上有奇數個點,更改後必然更改加號個數奇偶性)
*/
int main(){
scanf("%d",&n);
char line[50];
int ons=0;
for(int i=1;i<=2*n+1;i++){
scanf("%s",line+1);
for(int j=1;j<=2*n+1;j++){
ar[i][j]=(line[j]=='+'?1:0);
if(ar[i][j]==1)ons++;
}
}
//必有解
printf("There is solution:\n");
//折到第一列和第一行
if(ons%2==1){
for(int i=1;i<=2*n+1;i++){
ar[i][i]=(ar[i][i]==1?0:1);
printf("%d",i);
if(i!=2*n+1)printf(" ");
}
printf("\n");
}
for(int i=2;i<=2*n+1;i++){
for(int j=2;j<=2*n+1;j++){
if(ar[i][j]==1){
initans(1,i,1,j);
printans();
initans(1,i,j,1);
printans();
}
}
}
//使每一個折角上頂多有1個加號
for(int i=2;i<=2*n+1;i++){
if(ar[i][1]&&ar[1][i]){
initans(1,i,i,1);
printans();
initans(1,i,1,i);
printans();
}
}
system("pause");
return 0;
}