poj1681(枚举or高斯消元解mod2方程组)
题目链接: http://poj.org/problem?id=1681
题意: 有一个包含 n * n 个方格的正方形, w 表示其所在位置为白色, y 表示其所在位置为黄色. 对 (i, j) 位置进行一次操作则 (i, j), (i + 1, j), (i - 1, j), (i, j - 1), (i, j + 1) 位置的颜色变为原来的相反状态, 输出让所有方格都变成白色所需的最少操作步数, 若不能使所有方格都变成白色,则输出 inf .
思路: 这题和 poj 1222 (题解: http://www.cnblogs.com/geloutingyu/p/7565405.html) 类似, 同样也可以枚举第一行的所有操作, 或者解 mod2 方程组.
解法1:
注意要求出所有解法然后取操作数最小值.
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std; const int inf = 1e9;
const int MAXN = 1e2;
int mp[MAXN][MAXN], sol[MAXN][MAXN];
int n, ans = inf; int check(void){
int gel[MAXN][MAXN], cnt = ;
memcpy(gel, mp, sizeof(mp));
for(int i = ; i <= n; i++){
if(sol[][i]){
cnt++;
gel[][i] ^= ;
gel[][i - ] ^= ;
gel[][i + ] ^= ;
gel[][i] ^= ;
gel[][i] ^= ;
}
}
for(int i = ; i <= n; i++){
for(int j = ; j <= n; j++){
if(gel[i - ][j]){
cnt++;
sol[i][j] = ;
gel[i][j] ^= ;
gel[i][j - ] ^= ;
gel[i][j + ] ^= ;
gel[i - ][j] ^= ;
gel[i + ][j] ^= ;
}else sol[i][j] = ;
}
}
for(int i = ; i <= n; i++){
if(gel[n][i]) return inf;
}
return cnt;
} void dfs(int m){
if(m > n){
ans = min(ans, check());
return;
}
sol[][m] = ;
dfs(m + );
sol[][m] = ;
dfs(m + );
} int main(void){
int t;
string s;
cin >> t;
while(t--){
cin >> n;
for(int i = ; i <= n; i++){
cin >> s;
for(int j = ; j < s.size(); j++){
if(s[j] == 'w') mp[i][j + ] = ;
else mp[i][j + ] = ;
}
}
ans = inf;
dfs();
if(ans == inf) cout << "inf" << endl;
else cout << ans << endl;
}
return ;
}
解法2:
注意对于存在变元的情况需要枚举变元的所有组合情况取操作数最小值.
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std; const int inf = 1e9;
const int MAXN = 3e2;
int equ, var;//有equ个方程,var个变元,增广矩正行数为equ,列数为var+1,从0开始计数
int a[MAXN][MAXN];//增广矩正
int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
int free_num;//自由变元个数
int x[MAXN];//解集 int Gauss(void){//返回-1表示无解,0表示有唯一解,否则返回自由变元个数
int max_r, col, k;
free_num = ;
for(k = , col = ; k < equ && col < var; k++, col++){
max_r = k;
for(int i = k + ; i < equ; i++){
if(abs(a[i][col] > abs(a[max_r][col]))) max_r = i;
}
if(a[max_r][col] == ){
k--;
free_x[free_num++] = col;//这个是变元
continue;
}
if(max_r != k){
for(int j = col; j < var + ; j++){
swap(a[k][j], a[max_r][j]);
}
}
for(int i = k + ; i < equ; i++){
if(a[i][col] != ){
for(int j = col; j < var + ; j++){
a[i][j] ^= a[k][j];
}
}
}
}
for(int i = k; i < equ; i++){
if(a[i][col] != ) return -;//无解
}
if(k < var) return var - k;//返回自由变元个数
for(int i = var - ; i >= ; i--){
x[i] = a[i][var];
for(int j = i + ; j < var; j++){
x[i] ^= (a[i][j] && x[j]);
}
}
return ;
} void solve(void){
int op = Gauss();
if(op == -) cout << "inf" << endl;//无解
else if(op == ){//存在唯一解
int sol = ;
for(int i = ; i < var; i++){
sol += x[i];
}
cout << sol << endl;
}else{//存在多解,需要枚举自由变元找到最小需要的操作数
int sol = inf;
int tot = << op;//有op个变元,每个变元可取0或1,共有1<<op总情况
for(int i = ; i < tot; i++){//二进制枚举,i二进制位上为1的取1,为0的取0
int cnt = ;
for(int j = ; j < op; j++){
if(i & ( << j)){//当前第j位变元取1
x[free_x[j]] = ;
cnt++;
}else x[free_x[j]] = ;
}
for(int j = var - op - ; j >= ; j--){
int idx;
for(idx = j; idx < var; idx++){
if(a[j][idx]) break;
}
x[idx] = a[j][var];
for(int l = idx + ; l < var; l++){
if(a[j][l]) x[idx] ^= x[l];
}
cnt += x[idx];
}
sol = min(sol, cnt);
}
cout << sol << endl;
}
} int main(void){
int t, n;
string s;
cin >> t;
while(t--){
cin >> n;
equ = var = n * n;
for(int i = ; i < n; i++){
cin >> s;
for(int j = ; j < n; j++){
int cnt = i * n + j;
if(s[j] == 'w') a[cnt][var] = ;
else a[cnt][var] = ;
x[cnt] = ;
}
}
for(int i = ; i < equ; i++){//构造增广矩阵
int x1 = i / n;
int y1 = i % n;
for(int j = ; j < var; j++){
int x2 = j / n;
int y2 = j % n;
if(abs(x1 - x2) + abs(y1 - y2) < ) a[j][i] = ;
else a[j][i] = ;
}
}
solve();
}
return ;
}
poj1681(枚举or高斯消元解mod2方程组)的更多相关文章
- poj1222(枚举or高斯消元解mod2方程组)
题目链接: http://poj.org/problem?id=1222 题意: 有一个 5 * 6 的初始矩阵, 1 表示一个亮灯泡, 0 表示一个不亮的灯泡. 对 (i, j) 位置进行一次操作则 ...
- poj1830(高斯消元解mod2方程组)
题目链接:http://poj.org/problem?id=1830 题意:中文题诶- 思路:高斯消元解 mod2 方程组 有 n 个变元,根据给出的条件列 n 个方程组,初始状态和终止状态不同的位 ...
- poj1753(高斯消元解mod2方程组)
题目链接:http://poj.org/problem?id=1753 题意:一个 4*4 的棋盘,初始时上面放满了黑色或白色的棋子.对 (i, j) 位置进行一次操作后 (i, j), (i + 1 ...
- 【高斯消元解xor方程组】BZOJ2466-[中山市选2009]树
[题目大意] 给出一棵树,初始状态均为0,每反转一个节点的状态,相邻的节点(父亲或儿子)也会反转,问要使状态均为1,至少操作几次? [思路] 一场大暴雨即将来临,白昼恍如黑夜!happy! 和POJ1 ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元解XOR方程组)
http://poj.org/problem?id=1222 题意:现在有5*6的开关,1表示亮,0表示灭,按下一个开关后,它上下左右的灯泡会改变亮灭状态,要怎么按使得灯泡全部处于灭状态,输出方案,1 ...
- 【高斯消元解xor方程】BZOJ1923-[Sdoi2010]外星千足虫
[题目大意] 有n个数或为奇数或为偶数,现在进行m次操作,每次取出部分求和,告诉你这几次操作选取的数和它们和的奇偶性.如果通过这m次操作能得到所有数的奇偶性,则输出进行到第n次时即可求出答案:否则输出 ...
- bzoj千题计划187:bzoj1770: [Usaco2009 Nov]lights 燈 (高斯消元解异或方程组+枚举自由元)
http://www.lydsy.com/JudgeOnline/problem.php?id=1770 a[i][j] 表示i对j有影响 高斯消元解异或方程组 然后dfs枚举自由元确定最优解 #in ...
- [置顶] hdu 4418 高斯消元解方程求期望
题意: 一个人在一条线段来回走(遇到线段端点就转变方向),现在他从起点出发,并有一个初始方向, 每次都可以走1, 2, 3 ..... m步,都有对应着一个概率.问你他走到终点的概率 思路: 方向问 ...
- 【BZOJ】2466: [中山市选2009]树 高斯消元解异或方程组
[题意]给定一棵树的灯,按一次x改变与x距离<=1的点的状态,求全0到全1的最少次数.n<=100. [算法]高斯消元解异或方程组 [题解]设f[i]=0/1表示是否按第i个点的按钮,根据 ...
随机推荐
- python风格指南
还在让别人一眼就看出你是一只野生程序猿嘛,快来看看谷歌的python风格指南提升逼格吧! http://zh-google-styleguide.readthedocs.io/en/latest/go ...
- CPU, PSU, SPU的区别
It all started in January 2005 with Critical Patch Updates (CPU). Then Patch Set Updates (PSU) were ...
- linux中安装sqlmap
wget https://codeload.github.com/sqlmapproject/sqlmap/legacy.tar.gz/master //下载sqlmap tar zxvf maste ...
- mysql 打印随机数
select rand(); 这样取出来的数据是类似这样的: 0.5389902438400223 要几位自己取几位: 取得方法类似 select substr(concat("000000 ...
- SharedPreferences 用法
private void getUserInfoFromPref(){ /* * 保存到文件的方法 * * Constant.user = (User)Constant.readObjectFromF ...
- volatile关键字在多线程中的作用
- extends与implements
implements一般是实现接口. extends 是继承类. 接口一般是只有方法声明没有定义的, 那么java特别指出实现接口是有道理的,因为继承就有感觉是父类已经实现了方法,而接口恰恰是没有实现 ...
- 关于PDF的一些书籍
PDF Explained: The ISO Standard for Document Exchange https://ssearch.oreilly.com/?q=PDF+
- Git 之 配置文件与用户凭证
配置文件 Git的配置文件有三个: 系统配置: /private/etc/gitconfig 用户配置: ~/.gitconfig 项目配置:.git/config 用户凭证 由于Git和Github ...
- 数据结构与算法(Java版)_堆
完全二叉树叫做堆. 完全二叉树就是最后一个节点之前不允许有不满的节点,就是不允许有空洞. 可以使用数组来做完全二叉树(堆). 堆分为大顶堆和小顶堆.大顶堆就是根节点上的数字是最大的,小顶堆就是根节点上 ...