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 }

时间: 2024-08-10 23:26:16

poj 1753 poj3185的相关文章

[ACM训练] 算法初级 之 基本算法 之 枚举(POJ 1753+2965)

先列出题目: 1.POJ 1753 POJ 1753  Flip Game:http://poj.org/problem?id=1753 Sample Input bwwb bbwb bwwb bwww Sample Output 4 入手竟然没有思路,感觉有很多很多种情况需要考虑,也只能使用枚举方法才能解决了吧~ 4x4的数组来进行数据存储的话操作起来肯定非常不方便,这里借用位压缩的方法来存储状态,使用移位来标识每一个位置的的上下左右的位置操作. 详细看这里. 1.当棋盘状态id为0(全白)或

POJ 1753 Flip Game(dfs+枚举)

POJ 1753 题意: 输入一个4*4的图像,由黑白两色组成,定义一种操作为:改变某个格子内小球的颜色(黑变白,白变黑),同时其上下左右的格子内小球也将变色.求最少多少次操作能使之成为纯色图案. 思路: 对一个格子操作偶数次等于没有操作,操作奇数次等于操作一次,所以答案在0~16以及impossible之间. 从n=0开始枚举n次操作可能的组成情况,即操作哪几个格子,若某种组合能变图案为纯色则停止. 由于总组合数达到2^16,故枚举组合情况可以用dfs来进行回溯枚举. //还有一种方法是位运算

POJ 1753 Flip Game (DFS + 枚举)

题目:http://poj.org/problem?id=1753 这个题在开始接触的训练计划的时候做过,当时用的是DFS遍历,其机制就是把每个棋子翻一遍,然后顺利的过了,所以也就没有深究. 省赛前一次做PC2遇到了几乎一模一样的题,只不过是把棋盘的界限由4X4改为了5X5,然后一直跑不出结果来,但是当时崔老湿那个队过了,在最后总结的时候,崔老湿就说和这个题一样,不过要枚举第一行进行优化. 我以为就是恢复第一行然后第二行以此类推,不过手推一下结果是6不是4,就知道这个有问题. 问了崔老湿,问了+

【POJ 1753】Flip Game

[POJ 1753]Flip Game 二进制+(BFS)暴力枚举 原本用二位字符数组存 发现遍历困难 并且翻动棋子也难办 后来想到一维线性 下标 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 在图中即为 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 预处理出一个数组进行翻转 后来又发现预处理难办 灵光一现 由于只有黑白两色 可用1 0标记 看到1 0想到的当然就是二进制了 并且又做成了个线性 刚好16位二进制 一切迎刃而解 翻转可

poj 1753 Flip Game (bfs + 枚举)

链接:poj 1753 题意:这是翻棋游戏,给定4*4棋盘,棋子一面为黑色(用b表示),另一面为白色(用w表示),问至少要几步可以将棋子翻为全黑或者全白,如不能达到目的,输出"Impossible " 翻转规则:可以选定16个棋子中的任意一个,将其本身以及上下左右相邻的翻转过来 分析:其实每格棋子最多只可以翻转一次(实际是奇数次,但与翻转一次状态一样),只要其中一格重复翻了2次(不论是连续翻动还是不连翻动),那么它以及周边的棋子和没翻动时的状态是一致的,与最初状态未翻转一样,由此就可以

POJ 1753 Flip Game (高斯消元 枚举自由变元求最小步数)

题目链接 题意:4*4的黑白棋,求把棋全变白或者全变黑的最小步数. 分析:以前用状态压缩做过. 和上题差不多,唯一的不同是这个终态是黑棋或者白棋, 但是只需要把给的初态做不同的两次处理就行了. 感觉现在还只是会套模板,不能独立的思考,好伤心.... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath&g

[ACM] POJ 1753 Flip Game (枚举,BFS,位运算)

Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29921   Accepted: 12975 Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the

POJ 1753 Flip Game (迭代递归)

POJ 1753,题目链接http://poj.org/problem?id=1753. POJ 1753,题目链接http://poj.org/problem?id=1753. 总共有16个点.对某个点选择操作或者不操作.一共有2^16次方种可能. 从前往后枚举,保证不重复. 1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #includ

穷举(四):POJ上的两道穷举例题POJ 1411和POJ 1753

下面给出两道POJ上的问题,看如何用穷举法解决. [例9]Calling Extraterrestrial Intelligence Again(POJ 1411) Description A message from humans to extraterrestrial intelligence was sent through the Arecibo radio telescope in Puerto Rico on the afternoon of Saturday November 16