题目链接:http://codeforces.com/contest/724/problem/B
题意:给出n*m的数字阵,每行数都是1-m的全排列,最多可以交换2个数一次,整个矩阵可以交换两列一次。问在n+1次操作内是否可以让这整个矩阵每行都变成单调递增的。
先考虑不用交换列的情况,那么只需要关心每行的数字是否在自己的位置上。记下不在自己的位置上的数字个数,如果大于2则说明至少要交换2次。显然是不符合条件的。
接下来考虑交换列的情况,枚举所有列交换的可能,再看看交换过后是否符合每行只需要交换两个数就行了。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 22; 6 int G[maxn][maxn]; 7 int n, m; 8 9 bool ok(int G[maxn][maxn]) { 10 for(int i = 1; i <= n; i++) { 11 int cnt = 0; 12 for(int j = 1; j <= m; j++) { 13 if(G[i][j] != j) cnt++; 14 } 15 if(cnt > 2) return 0; 16 } 17 return 1; 18 } 19 20 int main() { 21 // freopen("in", "r", stdin); 22 while(~scanf("%d%d",&n,&m)) { 23 for(int i = 1; i <= n; i++) { 24 for(int j = 1; j <= m; j++) { 25 scanf("%d", &G[i][j]); 26 } 27 } 28 if(ok(G)) { 29 puts("YES"); 30 continue; 31 } 32 bool flag = 0; 33 for(int i = 1; i <= m; i++) { 34 if(flag) break; 35 for(int j = i+1; j <= m; j++) { 36 if(flag) break; 37 for(int k = 1; k <= n; k++) swap(G[k][i], G[k][j]); 38 if(ok(G)) flag = 1; 39 for(int k = 1; k <= n; k++) swap(G[k][i], G[k][j]); 40 } 41 } 42 printf("%s ", flag?"YES":"NO"); 43 } 44 return 0; 45 }