[POJ2965]The Pilots Brothers' refrigerator (搜索/位运算)

题意
游戏“The Pilots Brothers:跟随有条纹的大象”有一个玩家需要打开冰箱的任务。
冰箱门上有16个把手。每个手柄可以处于以下两种状态之一:打开或关闭。只有当所有把手都打开时,冰箱才会打开。手柄表示为矩阵4х4。您可以在任何位置[i,j](1≤i,j≤4)更改句柄的状态。但是,这也会更改第i行中所有句柄的状态以及第j列中的所有句柄。
任务是确定打开冰箱所需的最小手柄切换次数。
思路
一个和“费解的开关”,"棋盘翻转",这样的位运算的题目很像,只不过这次一次翻转1行+1列
其实可以用1个数就可以记录状态,但是我懒……
(其实是不会状压啦)
Code
#include<cstdio>
using namespace std;
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b) int x[], y[]; int map[][];
int ans=;
int ansX[],ansY[]; int read()
{
char ch = getchar();
while (ch!='-' && ch!='+') ch = getchar();
return ch=='-'?:;
} void build()
{
for(int i=;i<;i++)
for (int j = ; j < ; j++)
map[i][j] = read();
} void flip(int s)
{
int x1 = s / ;
int y1 = s % ;
for (int i = ; i < ; i++)
{
map[i][y1] ^= ;
map[x1][i] ^= ;
}
map[x1][y1] ^= ;
} bool check()
{
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
if (!map[i][j]) return ;
}
return ;
} void dfs(int s, int b)
{
if (check())
{
if (ans > b)
{
ans = b;
for (int i = ; i <= ans; i++)
ansX[i] = x[i], ansY[i] = y[i];
}
return;
} if (s >= ) return;
dfs(s + , b);
flip(s);
x[b + ] = s / + ;
y[b + ] = s % + ;
dfs(s + , b + );
flip(s);
return;
} int main()
{
build();
dfs(, );
printf("%d\n", ans);
for (int i = ; i <= ans; i++)
printf("%d %d\n", ansX[i], ansY[i]);
return ;
}
其他做法
博客上搜到的
放出来
注释也很详细了
用奇偶性做的
/* 参考高手的高效解法:
> 证明:要使一个为'+'的符号变为'-',必须其相应的行和列的操作数为奇数;可以证明,如果'+'位置对应的行和列上每一个位置都进行一次操作,则整个图只有这一'+'位置的符号改变,其余都不会改变.
> 设置一个4*4的整型数组,初值为零,用于记录每个点的操作数,那么在每个'+'上的行和列的的位置都加1,得到结果模2(因为一个点进行偶数次操作的效果和没进行操作一样,这就是楼上说的取反的原理),然后计算整型数组中一的
> 个数即为操作数,一的位置为要操作的位置(其他原来操作数为偶数的因为操作并不发生效果,因此不进行操作)
*********************************
此上证其可以按以上步骤使数组中值都为‘-’
********************************
在上述证明中将所有的行和列的位置都加1后,在将其模2之前,对给定的数组状态,将所有的位置操作其所存的操作数个次数,举例,如果a[i][j]==n,则对(i,j)操作n次,当所有的操作完后,即全为‘-’的数组。
其实就是不模2的操作,作了许多的无用功。
以上的操作次序对结果无影响,如果存在一个最小的步骤,则此步骤一定在以上操作之中。(简单说下:因为以上操作已经包含了所有可改变欲改变位置的操作了)
而模2后的操作是去掉了所有无用功之后的操作,此操作同样包含最小步骤。
但模2后的操作去掉任何一个或几个步骤后,都不可能再得到全为‘-’的。(此同样可证明:因为操作次序无影响,先进行最小步骤,得到全为‘-’,如果还剩下m步,则在全为‘-’的数组状态下进行这m步操作后还得到一个全为
‘-’的数组状态,此只能是在同一个位置进行偶数次操作,与前文模2后矛盾,所以m=0),因此模2后的操作即为最小步骤的操作。
*/
#include <iostream>
using namespace std; bool mark[][];
char s[][]; int main()
{
int i,j,k;
int ci[],cj[];
int nas = ;
memset(mark,,sizeof(mark));
for(i = ;i < ;i++)
cin >> s[i];
for(i = ;i < ;i++)
for(j = ;j < ;j++)
{
char c = s[i][j];
if(c == '+')
{
mark[i][j] = !mark[i][j];
for(k = ;k < ;k++)
{
mark[i][k] = !mark[i][k];
mark[k][j] = !mark[k][j];
}
} }
for(i = ;i < ;i++)
for(j = ;j < ;j++)
if(mark[i][j] == true)
{
ci[nas] = i + ;
cj[nas] = j + ;
nas ++;
}
printf("%d\n",nas);
for(i = ;i < nas;i++)
{
printf("%d %d\n",ci[i],cj[i]);
}
return ;
}
[POJ2965]The Pilots Brothers' refrigerator (搜索/位运算)的更多相关文章
- POJ2965——The Pilots Brothers' refrigerator
The Pilots Brothers' refrigerator Description The game “The Pilots Brothers: following the stripy el ...
- POJ - 2965 The Pilots Brothers' refrigerator(压位+bfs)
The game “The Pilots Brothers: following the stripy elephant” has a quest where a player needs to op ...
- poj2965 The Pilots Brothers' refrigerator
题目链接:http://poj.org/problem?id=2965 分析:1.这道题和之前做的poj1753题目差不多,常规思路也差不多,但是除了要输出最少步数外,还要输出路径.做这道题的时候在怎 ...
- poj2965 The Pilots Brothers' refrigerator —— 技巧性
题目链接:http://poj.org/problem?id=2965 题解:自己想到的方法是枚举搜索,结果用bfs和dfs写都超时了.网上拿别人的代码试一下只是刚好不超时的,如果自己的代码在某些方面 ...
- POJ 2965 The Pilots Brothers' refrigerator 位运算枚举
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 151 ...
- POJ 2965 The Pilots Brothers' refrigerator 暴力 难度:1
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16868 ...
- 枚举 POJ 2965 The Pilots Brothers' refrigerator
题目地址:http://poj.org/problem?id=2965 /* 题意:4*4的矩形,改变任意点,把所有'+'变成'-',,每一次同行同列的都会反转,求最小步数,并打印方案 DFS:把'+ ...
- POJ 2965. The Pilots Brothers' refrigerator 枚举or爆搜or分治
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22286 ...
- POJ2965The Pilots Brothers' refrigerator(枚举+DFS)
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22057 ...
随机推荐
- (二分查找 拓展) leetcode278. First Bad Version
You are a product manager and currently leading a team to develop a new product. Unfortunately, the ...
- NOI-OJ 2.2 ID:6261 汉诺塔
思路 汉诺塔是递归思想最经典的例子,通过递归不断缩小问题,将n个盘子的问题简化n-1个,直至1个. 三个盘子,分别为A:from,B:to,C:by(A为起点盘,B为目标盘,C为中转盘) 过程 将1- ...
- [译]Ocelot - Load Balancer
原文 可以对下游的服务进行负载均衡. 提供了下面几种负载均衡: LeastConnection - tracks which services are dealing with requests an ...
- 修改WEB项目的发布名称
1.在要修改的项目上单击右键选择properties,修改web选项中的Web Context-root中的发布名称即可,但需要注意的是修改发布名称后需要将项目从服务器中先移除后再重新添加.
- js中escape对应的C#解码函数 UrlDecode
js中escape对应的C#解码函数 System.Web.HttpUtility.UrlDecode(s),使用过程中有以下几点需要注意 js中escape对应的C#解码函数 System.We ...
- linux 远程 telnet
linux 远程 telnet [ root@test1 ~]# yum install telnet* (安装的三个包 xinetd . telnet-server.telnet) [ roo ...
- 移动端调用电话、短信、唤起QQ和使用百度地图
H5能很方便地实现这些功能,都是一句代码搞定 调用电话 <a href="tel:12345678"> 短信 <a href='sms:12345678'> ...
- Docker入门-安装(一)
Docker 在CentOS 7.0下安装Docker, CentOS 7.0默认使用的是firewall作为防火墙 查看防火墙状态 firewall-cmd --state 停止firewall ...
- 10. linux输入子系统/input 设备【转】
转自:https://www.cnblogs.com/crmn/articles/6696819.html 按键事件信息之上报绝对事件信息之上报相对事件信息之上报功能键驱动编写多点触控事件的上报 只产 ...
- OpenCV掩模mask的原理和作用
一.什么是掩模mask OpenCV中很多函数都带有一个mask参数,mask被称为掩模.图像掩模一般用来对处理的图像(全部或者局部)进行遮挡,来控制图像处理的区域或处理过程. 二.掩模原理 掩模一般 ...