$n leq 12,m leq 12$,$n$行$m$列小写字母,现可做无数次操作:交换两行;交换两列。问是否有可能把他变成中心对称的。
没有去想分组枚举的复杂度QAQ
行和列的操作顺序是随意的。假如说在一种最优方案中,操作是行行行……行列列列……列行行行……行列列列……列,那您把后面那堆行和前面那堆列换一下准保没问题:在一行的字母是不会变成不在同一行的,在一列的字母是不会变成不在同一列的,所以我瞄准最优方案,先把行放好位置,然后调列,一定能调好。可能比较抽象,反正他是对的,具体证明出门见其他大牛博客。
还有一件事,我枚举一种分配方案不需要枚举$n!$,很多都是重复的。怎么讲?先考虑这:我一种行的放法确定好,然后调列看合不合法。要合法的话,每个列都要和另一个列配上,这里的配上,就是一个取反后和另一个相等。如果m是奇数,那得有个列来当回文串放中间。这样子,假设现在放行的方案是$(p_1,p_2,...,p_n)$,如果咱变成$(p_2,p_1,...,p_n,p_{n-1})$,那跟前面那种是完全一样的(如果前面那种配上了这种也配上,如果前面那种配不上这种也配不上)。因此我只要把行打包成$n/2$对,然后每一对对称放,复杂度就会变成:多少啊,我每次从剩下的人里选一个考虑他配谁,选谁无所谓因为谁都要配,然后枚举他配谁,这样复杂度就是$(n-1)*(n-3)*...=(n-1)!!$。最大到10000多一点。行列都这么枚举加剪枝可以过。
诶您啥啊列何必像行那样枚举,每次枚举配上就配上了不改了,因此列枚举复杂度可以变成$n*m*m$,排序+二分可以变成$n*m*log_2m$。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<time.h> 5 //#include<complex> 6 //#include<set> 7 #include<algorithm> 8 //#include<math.h> 9 #include<stdlib.h> 10 using namespace std; 11 12 int n,m; 13 char mp[15][15]; 14 15 int a[15]; bool vis[15],ans=0; 16 17 bool v2[15]; 18 bool check() 19 { 20 // for (int i=1;i<=n;i++) cout<<a[i]<<' ';cout<<endl; 21 memset(v2,0,sizeof(v2)); 22 bool used=(m&1); 23 for (int i=1;i<=m;i++) if (!v2[i]) 24 { 25 bool flag=0; 26 for (int j=i+1;j<=m;j++) if (!v2[j]) 27 { 28 bool ff=1; 29 for (int k=1;k<=n;k++) if (mp[a[k]][i]!=mp[a[n-k+1]][j]) ff=0; 30 if (ff) {v2[j]=1; flag=1; break;} 31 } 32 if (!flag) 33 { 34 if (used) 35 { 36 bool ff=1; 37 for (int k=1;k<=n;k++) if (mp[a[k]][i]!=mp[a[n-k+1]][i]) ff=0; 38 if (ff) used=0; 39 else return 0; 40 } 41 else return 0; 42 } 43 } 44 return 1; 45 } 46 47 void dfs(int cur,int pos,bool odd) 48 { 49 if (ans) return; 50 if (cur>n) {ans=check(); return;} 51 if (vis[cur]) {dfs(cur+1,pos,odd); return;} 52 53 for (int i=cur+1;i<=n;i++) if (!vis[i]) 54 { 55 a[pos]=i; a[n-pos+1]=cur; 56 vis[i]=1; 57 dfs(cur+1,pos+1,odd); 58 vis[i]=0; 59 } 60 if (odd) 61 { 62 a[(n>>1)+1]=cur; 63 dfs(cur+1,pos,0); 64 } 65 } 66 67 int main() 68 { 69 scanf("%d%d",&n,&m); 70 for (int i=1;i<=n;i++) scanf("%s",mp[i]+1); 71 dfs(1,1,n&1); 72 puts(ans?"YES":"NO"); 73 return 0; 74 }