POJ 1222【异或高斯消元|二进制状态枚举】
题目链接:【http://poj.org/problem?id=1222】
题意:Light Out,给出一个5 * 6的0,1矩阵,0表示灯熄灭,反之为灯亮。输出一种方案,使得所有的等都被熄灭。
题解:首先可以用高斯消元来做,对于每个点,我们列出一个方程,左边是某个点和它相邻的点,他们的异或值等于右边的值(灯亮为1 ,灯灭为0),然后求一个异或高斯消元就可以了。可以用bitset优化,或者__int128优化(其实unsigned就可以了)。
还可以枚举第一行的按开关的状态共有1<<6中状态,从上到下检查,如果某一行的某一个灯是亮的,那只有用按下下一行的这个位置的开关使得这个位置的灯熄灭,最后判断最后一行是否熄灭就可以了。
高斯消元:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 35;
int T;
int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
int a[maxn][maxn], ans[maxn];
int idx(int x, int y)
{
return (x - 1) * 6 + y;
}
void Guess()
{
int i, j, k, l;
for(i = 1, j = 1; i <= 30 && j <= 30; j++)
{
for(k = i; k <= 30; k++)
if(a[k][j]) break;
if(a[k][j])
{
for(l = 1; l <= 31; l++) swap(a[i][l], a[k][l]);
for(l = 1; l <= 30; l++) //debug从1开始(回代)
{
if(l != i && a[l][j])
for(k = 1; k <= 31; k++)
a[l][k] ^= a[i][k];
}
i++;
}
}
for(int j = 1; j < i; j++) ans[j] = a[j][31];
//自由元不是必须按的,则标记为0
}
int main ()
{
int ic =0;
scanf("%d", &T);
while(T--)
{
memset(a, 0, sizeof(a));
for(int i = 1; i <= 5; i++)
for(int j = 1; j <= 6; j++)
{
scanf("%d", &a[idx(i, j)][31]);
}
for(int i = 1; i <= 30; i++)
{
a[i][i] = 1;
int X = (i - 1) / 6 + 1;
int Y = i - idx(X, 0);
for(int j = 0; j < 4; j++)
{
int x = X + dir[j][1];
int y = Y + dir[j][0];
if(x < 1 || y < 1 || x > 5 || y > 6) continue;
a[i][idx(x, y)] = 1;
}
}
Guess();
printf("PUZZLE #%d\n",++ic);
for(int i = 1; i <= 30; i++)
{
printf("%d", ans[i]);
if(!(i % 6)) printf("\n");
else printf(" ");
} }
return 0;
}
Bitset:
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 35;
int T;
int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
bitset<maxn>a[maxn];
int idx(int x, int y)
{
return (x - 1) * 6 + y;
}
void Guess()
{
int i, j, k, l;
for(i = 1, j = 1; i <= 30 && j <= 30; j++)
{
for(k = i; k <= 30; k++) if(a[k][j]) break;
if(a[k][j])
{
swap(a[i], a[k]);
for(l = 1; l <= 30; l++) //debug从1开始(回代)
if(l != i && a[l][j]) a[l] ^= a[i];
i++;
}
}
}
int main ()
{
int ic = 0;
scanf("%d", &T);
while(T--)
{
for(int i = 1; i <= 31; i++) a[i].reset();
for(int i = 1; i <= 5; i++)
for(int j = 1; j <= 6; j++)
{
int t = 0 ;
scanf("%d", &t);
if(t) a[idx(i, j)].set(31);
}
for(int i = 1; i <= 30; i++)
{
a[i][i] = 1;
int X = (i - 1) / 6 + 1;
int Y = i - idx(X, 0);
for(int j = 0; j < 4; j++)
{
int x = X + dir[j][1];
int y = Y + dir[j][0];
if(x < 1 || y < 1 || x > 5 || y > 6) continue;
a[i].set(idx(x, y));
}
}
Guess();
printf("PUZZLE #%d\n", ++ic);
for(int i = 1; i <= 30; i++)
{
if(a[i][31]) printf("1");
else printf("0");
if(!(i % 6)) printf("\n");
else printf(" ");
}
}
return 0;
}
unsigned:
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 35;
int T;
int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
unsigned long long a[maxn];
int idx(int x, int y)
{
return (x - 1) * 6 + y;
}
void Guess()
{
int i, j, k, l;
for(i = 1, j = 1; i <= 30 && j <= 30; j++)
{
for(k = i; k <= 30; k++) if(a[k] & ((unsigned long long)1 << (j - 1))) break;
if(a[k] & ((unsigned long long)1 << (j - 1)))
{
swap(a[i], a[k]);
for(l = 1; l <= 30; l++)
if(l != i && a[l] & ((unsigned long long)1 << (j - 1))) a[l] ^= a[i];
i++;
}
}
}
int main ()
{
int ic = 0;
scanf("%d", &T);
while(T--)
{
for(int i = 1; i <= 31; i++) a[i] = 0;
for(int i = 1; i <= 5; i++)
for(int j = 1; j <= 6; j++)
{
int t = 0 ;
scanf("%d", &t);
if(t) a[idx(i, j)] |= ((unsigned long long)1 << 30);
}
for(int i = 1; i <= 30; i++)
{
a[i] |= ((unsigned long long)1 << (i - 1));
int X = (i - 1) / 6 + 1;
int Y = i - idx(X, 0);
for(int j = 0; j < 4; j++)
{
int x = X + dir[j][1];
int y = Y + dir[j][0];
if(x < 1 || y < 1 || x > 5 || y > 6) continue;
a[i] |= ((unsigned long long)1 << idx(x, y) - 1);
}
}
Guess();
printf("PUZZLE #%d\n", ++ic);
for(int i = 1; i <= 30; i++)
{
if(a[i] & ((unsigned long long)1 << 30)) printf("1");
else printf("0");
if(!(i % 6)) printf("\n");
else printf(" ");
}
}
return 0;
}
二进制状态枚举:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 15;
int T;
int a[maxn][maxn], tmp[maxn][maxn], ans[maxn][maxn];
int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
void flip(int x, int y)
{
ans[x][y] = 1;
tmp[x][y] ^= 1;
for(int i = 0; i < 4; i++)
{
int X = x + dir[i][0];
int Y = y + dir[i][1];
if(X < 1 || X > 5 || Y < 1 || Y > 6) continue;
tmp[X][Y] ^= 1;
}
}
int main ()
{
int ic = 0;
scanf("%d", &T);
while(T--)
{
for(int i = 1; i <= 5; i++)
for(int j = 1; j <= 6; j++)
scanf("%d", &a[i][j]);
for(int k = 0; k <= (1 << 6) - 1; k++)
{
for(int i = 1; i <= 5; i++)
for(int j = 1; j <= 6; j++)
tmp[i][j] = a[i][j], ans[i][j] = 0;
int t = k, pos = 1;
while(t)
{
if(t & 1) flip(1, pos);
t >>= 1;
pos++;
}
for(int i = 1; i <= 4; i++)
for(int j = 1; j <= 6; j++)
if(tmp[i][j]) flip(i + 1, j);
int sum = 0;
for(int i = 1; i <= 6; i++)
sum += tmp[5][i];
if(!sum) break;
}
printf("PUZZLE #%d\n",++ic);
for(int i = 1; i <= 5; i++)
{
for(int j = 1; j <= 5; j++)
printf("%d ", ans[i][j]);
printf("%d\n", ans[i][6]);
}
}
return 0;
}
POJ 1222【异或高斯消元|二进制状态枚举】的更多相关文章
- POJ 1681 Painter's Problem 【高斯消元 二进制枚举】
任意门:http://poj.org/problem?id=1681 Painter's Problem Time Limit: 1000MS Memory Limit: 10000K Total ...
- POJ 1753 Flip Game(高斯消元+状压枚举)
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 45691 Accepted: 19590 Descr ...
- poj1830开关问题——异或高斯消元
题目:http://poj.org/problem?id=1830 根据题意,构造出n元方程组: a(1,1)x1 ^ a(1,2)x2 ^ a(1,3)x3 ... a(1,n)xn = st1 ^ ...
- SGU 260.Puzzle (异或高斯消元)
题意: 有n(<200)个格子,只有黑白两种颜色.可以通过操作一个格子改变它和其它一些格子的颜色.给出改变的关系和n个格子的初始颜色,输出一种操作方案使所有格子的颜色相同. Solution: ...
- Luogu3164 CQOI2014 和谐矩阵 异或高斯消元
传送门 题意:给出$N,M$,试构造一个$N \times M$的非全$0$矩阵,其中所有格子都满足:它和它上下左右四个格子的权值之和为偶数.$N , M \leq 40$ 可以依据题目中的条件列出有 ...
- POJ 1830 开关问题 高斯消元,自由变量个数
http://poj.org/problem?id=1830 如果开关s1操作一次,则会有s1(记住自己也会变).和s1连接的开关都会做一次操作. 那么设矩阵a[i][j]表示按下了开关j,开关i会被 ...
- A - The Water Bowls POJ - 3185 (bfs||高斯消元)
题目链接:https://vjudge.net/contest/276374#problem/A 题目大意:给你20个杯子,每一次操作,假设当前是对第i个位置进行操作,那么第i个位置,第i+1个位置, ...
- POJ 1166 The Clocks 高斯消元 + exgcd(纯属瞎搞)
依据题意可构造出方程组.方程组的每一个方程格式均为:C1*x1 + C2*x2 + ...... + C9*x9 = sum + 4*ki; 高斯消元构造上三角矩阵,以最后一个一行为例: C*x9 = ...
- POJ 1830 开关问题 (高斯消元)
题目链接 题意:中文题,和上篇博客POJ 1222是一类题. 题解:如果有解,解的个数便是2^(自由变元个数),因为每个变元都有两种选择. 代码: #include <iostream> ...
随机推荐
- 你必须了解Spring的生态
Spring不止是提供了IOC.AOP的功能,还提供了大量的基于Spring的项目,拿来用就行了,用于一站式开发,大大降低了开发的难度. 下面列举下主要的一些Spring的生态项目: Spring B ...
- 《JavaScript 实战》:JavaScript 实现拖拽缩放效果
拖拉缩放效果,实现通过鼠标拖动来调整层的面积(宽高)大小,例如选框效果.这里的拖拉缩放比一般的选框复杂一点,能设置八个方位(方向)的固定触发点,能设置最小范围,最大范围和比例缩放. 跟拖放效果一样,程 ...
- HDFS默认副本数为什么是3
转载自: https://www.cnblogs.com/bugchecker/p/why_three_replications_for_HDFS_in_engineer.html HDFS采用一种称 ...
- 【洛谷 P3191】 [HNOI2007]紧急疏散EVACUATE(二分答案,最大流)
题目链接 sb错误调了3hour+.. bfs预处理出每个\(.\)到每个\(D\)的最短距离. 二分时间\(t\),把每个\(D\)拆成\(t\)个点,这\(t\)个点两两连边,流量\(INF\)表 ...
- Count on a tree(SPOJ COT + 树上第k大 + 主席树 + LCA)
题目链接:https://www.spoj.com/problems/COT/en/ 题目: 题意: 给你一棵有n个节点的树,求节点u到节点v这条链上的第k大. 思路: 我们首先用dfs进行建题目给的 ...
- NYOJ 136 等式 (哈希)
题目链接 描述 有以下等式:a1x13+a2x23+a3x33+a4x43+a5*x53=0 x1,x2,x3,x4,x5都就在区间[-50,50]之间的整数,且x1,x2,x3,x4,x5都不等于0 ...
- 深入理解Spring系列之六:bean初始化
转载 https://mp.weixin.qq.com/s/SmtqoELzBEdZLo8wsSvUdQ <深入理解Spring系列之四:BeanDefinition装载前奏曲>中提到,对 ...
- arch安装完成之后不能使用笔记本自带的无线网卡
问题描述如下 我笔记本的wifi网卡识别不了,不知道为什么?? 使用ifconfig -a 只列出了有线网卡以及外接的无线网卡如下 enp4s0f1: flags=<UP,BROADCAST,M ...
- linux和windows共享文件,通过samba
SAMBA共享1.安装samba:可以先检查下是否已经安装:rpm -qa | grep samba,没有的话自己安装下,这里介绍下基于RPM包的一种在线安装模式yumyum是一种快速安装模式,它会自 ...
- 64_s1
SAASound-3.2-17.fc26.i686.rpm 13-Feb-2017 22:13 27650 SAASound-3.2-17.fc26.x86_64.rpm 13-Feb-2017 23 ...