poj 1753 poj3185

两道题目类似,自己写的挫一直不对,后来祭出了kuangbin模板(枚举变元求最小解),慢慢练吧。。。

贴出1753的代码 3185直接改改初始化就行了

  1 #include <queue>
  2 #include <set>
  3 #include <map>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <cstdio>
  7 #include <iostream>
  8 
  9 using namespace std;
 10 //对2取模的01方程组
 11 const int MAXN = 300;
 12 //有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var
 13 int equ,var;
 14 int a[MAXN][MAXN]; //增广矩阵
 15 int x[MAXN]; //解集
 16 int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
 17 int free_num;//自由变元的个数
 18 
 19 //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
 20 int Gauss()
 21 {
 22     int max_r,col,k;
 23     free_num = 0;
 24     for(k = 0, col = 0 ; k < equ && col < var ; k++, col++)
 25     {
 26         max_r = k;
 27         for(int i = k+1;i < equ;i++)
 28         {
 29             if(abs(a[i][col]) > abs(a[max_r][col]))
 30                 max_r = i;
 31         }
 32         if(a[max_r][col] == 0)
 33         {
 34             k--;
 35             free_x[free_num++] = col;//这个是自由变元
 36             continue;
 37         }
 38         if(max_r != k)
 39         {
 40             for(int j = col; j < var+1; j++)
 41                 swap(a[k][j],a[max_r][j]);
 42         }
 43         for(int i = k+1;i < equ;i++)
 44         {
 45             if(a[i][col] != 0)
 46             {
 47                 for(int j = col;j < var+1;j++)
 48                     a[i][j] ^= a[k][j];
 49             }
 50         }
 51     }
 52     for(int i = k;i < equ;i++)
 53         if(a[i][col] != 0)
 54             return -1;//无解
 55     if(k < var) return var-k;//自由变元个数
 56     //唯一解,回代
 57     for(int i = var-1; i >= 0;i--)
 58     {
 59         x[i] = a[i][var];
 60         for(int j = i+1;j < var;j++)
 61             x[i] ^= (a[i][j] && x[j]);
 62     }
 63     return 0;
 64 }
 65 int n;
 66 
 67 const int INF = 0x3f3f3f3f;
 68 int solve()
 69 {
 70     int t = Gauss();
 71     if(t == -1)
 72     {
 73         return INF;
 74     }
 75     else if(t == 0)
 76     {
 77         int ans = 0;
 78         for(int i = 0;i < n*n;i++)
 79             ans += x[i];
 80         return ans;
 81     }
 82     else
 83     {
 84         //枚举自由变元
 85         int ans = INF;
 86         int tot = (1<<t);
 87         for(int i = 0;i < tot;i++)
 88         {
 89             int cnt = 0;
 90             for(int j = 0;j < t;j++)
 91             {
 92                 if(i&(1<<j))
 93                 {
 94                     x[free_x[j]] = 1;
 95                     cnt++;
 96                 }
 97                 else x[free_x[j]] = 0;
 98             }
 99             for(int j = var-t-1;j >= 0;j--)
100             {
101                 int idx;
102                 for(idx = j;idx < var;idx++)
103                     if(a[j][idx])
104                         break;
105                 x[idx] = a[j][var];
106                 for(int l = idx+1;l < var;l++)
107                     if(a[j][l])
108                         x[idx] ^= x[l];
109                 cnt += x[idx];
110             }
111             ans = min(ans,cnt);
112         }
113         return ans;
114     }
115 }
116 
117 void init(int n)
118 {
119         memset(a,0,sizeof(a));
120         int x,xx,y,yy;
121         for(int i=0;i<n*n;i++){
122                 x = i/n;
123                 y = i%n;
124             for(int j=0;j<n*n;j++){
125                 xx = j/n;
126                 yy = j%n;
127                 if(abs(x-xx)+abs(y-yy)<=1) a[i][j] = 1;
128                 else a[i][j] = 0;
129             }
130         }
131 }
132 int main()
133 {
134 
135     char s[50][50];
136         int n;
137         n = 4;
138         equ = var = n*n;
139         for(int i=0;i<n;i++){
140             scanf("%s",s[i]);
141         }
142         init(n);
143         for(int i=0;i<n*n;i++){
144             if(s[i/n][i%n] != 'b') a[i][n*n] = 1;
145         }
146 
147        int k = 0,kk = 0;
148        int res1 = solve();
149 
150        init(n);
151        for(int i=0;i<n*n;i++){
152             if(s[i/n][i%n] == 'b') a[i][n*n] = 1;
153         }
154        int res2 = solve();
155        if(res1 == INF && res2 == INF) printf("Impossible\n");
156        else{
157        printf("%d\n",min(res1,res2));
158        }
159 
160 
161     return 0;
162 }
View Code

 

posted @ 2015-11-08 12:49  lmlyzxiao  阅读(160)  评论(0编辑  收藏  举报