标签:spl Painter targe amp ++ har src 题意 mon
任意门:http://poj.org/problem?id=1681
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7667 | Accepted: 3624 |
Description
Input
Output
Sample Input
2 3 yyy yyy yyy 5 wwwww wwwww wwwww wwwww wwwww
Sample Output
0 15
Source
一个二维矩阵, 输入每个格子的初始颜色,可以进行的操作是 粉刷一个格子则相邻的上下左右四个各自颜色都会取反(只有两种颜色);
问最后把全部各自涂成黄色的最小操作数;
根据题意,每个各自都是一个变元,根据各自之间的相邻关系构造增广矩阵;
高斯消元求出自由元个数 sum;
二进制枚举方案,找出最小的操作数;
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #define INF 0x3f3f3f3f 6 #define LL long long 7 using namespace std; 8 const int MAXN = 300; 9 10 int equ, var; 11 int a[MAXN][MAXN]; 12 char str[MAXN][MAXN]; 13 int x[MAXN]; 14 int free_x[MAXN]; 15 int free_num; 16 int N; 17 18 int Gauss() 19 { 20 int maxRow, col, k; 21 free_num = 0; 22 for(k = 0, col = 0; k < equ && col < var; k++, col++){ 23 maxRow = k; 24 for(int i = k+1; i <equ; i++){ 25 if(abs(a[i][col]) > abs(a[maxRow][col])) 26 maxRow = i; 27 } 28 if(a[maxRow][col] == 0){ //最大的都为0说明该列下面全是 0 29 k--; 30 free_x[free_num++] = col; //说明col是自由元 31 continue; 32 } 33 if(maxRow != k){ //交换行 34 for(int j = col; j < var+1; j++) 35 swap(a[k][j], a[maxRow][j]); 36 } 37 for(int i = k+1; i < equ; i++){ //消元 38 if(a[i][col] != 0){ 39 for(int j = col; j < var+1; j++){ 40 a[i][j] ^= a[k][j]; 41 } 42 } 43 } 44 } 45 for(int i = k; i< equ; i++){ 46 if(a[i][col] != 0) return -1; //无解 47 } 48 if(k < var) return var-k; //返回自由元个数 49 50 for(int i = var-1; i >= 0; i--){ //唯一解,回代 51 x[i] = a[i][var]; 52 for(int j = i+1; j < var; j++){ 53 x[i] ^= (a[i][j] && x[j]); 54 } 55 } 56 return 0; 57 } 58 59 void init() 60 { 61 memset(a, 0, sizeof(a)); 62 memset(x, 0, sizeof(x)); 63 equ = N*N; 64 var = N*N; 65 for(int i = 0; i < N; i++){ //构造增广矩阵 66 for(int j = -0; j < N; j++){ 67 int t = i*N+j; 68 a[t][t] = 1; 69 if(i > 0) a[(i-1)*N+j][t] = 1; 70 if(i < N-1) a[(i+1)*N+j][t] = 1; 71 if(j > 0) a[i*N+j-1][t] = 1; 72 if(j < N-1) a[i*N+j+1][t] = 1; 73 } 74 } 75 } 76 77 void solve() 78 { 79 int t = Gauss(); 80 if(t == -1){ //无解 81 printf("inf\n"); 82 return; 83 } 84 else if(t == 0){ //唯一解 85 int ans = 0; 86 for(int i = 0; i < N*N; i++){ 87 ans += x[i]; 88 } 89 printf("%d\n", ans); 90 return; 91 } 92 else{ //多解,需要枚举自由元 93 int ans = INF; 94 int tot = 1<<t; 95 int cnt = 0; 96 for(int i = 0; i < tot; i++){ 97 cnt = 0; 98 for(int j = 0; j < t; j++){ 99 if(i&(1<<j)){ 100 x[free_x[j]] = 1; 101 cnt++; 102 } 103 else x[free_x[j]] = 0; 104 } 105 106 for(int j = var-t-1; j >= 0; j--){ 107 int index; 108 for(index = j; index < var; index++){ 109 if(a[j][index]) break; 110 } 111 x[index] = a[j][var]; 112 113 for(int s = index+1; s < var; s++) 114 if(a[j][s]) x[index] ^= x[s]; 115 116 cnt+=x[index]; 117 } 118 ans = min(ans, cnt); 119 } 120 printf("%d\n", ans); 121 } 122 } 123 124 int main() 125 { 126 int T_case; 127 int tpx, tpy; 128 scanf("%d", &T_case); 129 while(T_case--){ 130 scanf("%d", &N); 131 init(); 132 for(int i = 0; i < N; i++){ 133 scanf("%s", str[i]); 134 for(int j = 0; j < N; j++){ 135 tpx = i*N+j, tpy = N*N; 136 if(str[i][j] == ‘y‘) a[tpx][tpy] = 0; 137 else a[tpx][tpy] = 1; 138 } 139 } 140 solve(); 141 } 142 return 0; 143 }
POJ 1681 Painter's Problem 【高斯消元 二进制枚举】
标签:spl Painter targe amp ++ har src 题意 mon
原文地址:https://www.cnblogs.com/ymzjj/p/9973367.html