【模拟+递归+位运算】POJ1753-Flip Game
由于数据规模不大,利用爆搜即可。第一次用位运算写的,但是转念一想应该用递归更加快,因为位运算没有剪枝啊(qДq )
【思路】
位运算:时间效率较低(172MS),有些辜负了位运算的初衷。首先将二维数组倒序看作一个二进制数num。我们假设1代表翻转,0代表不翻转,可以发现以下规律:0 xor 1=1,1 xor 1=0;0 xor 0=0,1 xor 0=1,恰巧满足异或运算。我们假设另一个二进制数i∈[0,2^16),通过异或运算就可以模拟出所有清形。
用check和i进行&操作可以求出以哪些位置为中心进行翻转。假设当前要翻转的方格在二进制数num中所在位数为k,则翻转它时同时翻转的四个方格(假设存在的话)分别为(k-1),(k+1),(k-4),(k+4),则turn[k]=在这几位为1,其余均为0的二进制数,我在草稿纸上手工计算之后直接设在数组中。这样的好处在于,用turn与now直接进行异或操作,即可求出翻转后的情形。
之后通过求i的二进制中1的个数即可。这步操作有一个较为简便的方法,通过草稿纸上模拟就可以领悟。
{
int count = ;
while(x)
{
x = x & ( x - );
count++;
}
printf("count = %d/n", count);
}
上述方法非常实用,要牢记。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int INF=;
int num,min;
int check[]={,,,,,,,,,,,,,,,};
int turn[]={,,,,,,,,,,,,,,,}; void init()
{
int k=;
for (int i=;i<;i++)
{
for (int j=;j<;j++)
{
char c;
scanf("%c",&c);
if (c=='w') num+=k;
k*=;
}
getchar();
}
} int mainprocess()
{
int min=INF;
for (int i=;i<;i++)
{
int now=num^i;
for (int j=;j<;j++)
if (check[j]&i)
{
now=now^turn[j];
}
if (now== || now==)
{
int ans=,x=i;
while (x)
{
x=x & (x-);
ans++;
}
if (ans<min) min=ans;
}
}
if (min==INF) return -;
else return min;
} int main()
{
init();
int output=mainprocess();
if (output==-) cout<<"Impossible"; else cout<<output;
cout<<endl;
return ;
}
此外还可以通过递归+剪枝来完成,效率较高(47ms),计算量较小。值得注意的是c++中如果将数组传入子程序,传入的其实是地址。所以必须在子程序中设置临时数组来保存当前状态,回溯时再还给原来的数组。注意,这个临时数组必须在子程序中,我第一次写的时候误将它写在了主程序中,那么临时数组就完全失去了它的意义。
剪枝:如果当前情况下需要翻转的次数已经小于最小值,则递归不需要再继续。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int INF=;
int map[][];
int dx[]={,,,-};
int dy[]={,-,,};
int ans; void recurrence(int step,int turn)
{
int tempmap[][];
if (turn>=ans) return;
if (step==)
{
int sum=;
for (int i=;i<;i++)
for (int j=;j<;j++) sum+=map[i][j];
if (sum== || sum==) ans=turn;
}
else
{
for (int k1=;k1<;k1++)
for (int k2=;k2<;k2++) tempmap[k1][k2]=map[k1][k2]; for (int i=;i<;i++)
{
if (i==)
{
int x=step/,y=step%;
map[x][y]=-map[x][y];
for (int d=;d<;d++)
if (x+dx[d]>= && x+dx[d]< && y+dy[d]>= && y+dy[d]<) map[x+dx[d]][y+dy[d]]=-map[x+dx[d]][y+dy[d]];
}
recurrence(step+,turn+i);
for (int k1=;k1<;k1++)
for (int k2=;k2<;k2++) map[k1][k2]=tempmap[k1][k2];
}
}
} int main()
{
ans=INF;
for (int i=;i<;i++)
{
char c;
for (int j=;j<;j++)
{
scanf("%c",&c);
if (c=='w') map[i][j]=; else map[i][j]=;
}
getchar();
}
recurrence(,);
if (ans!=INF) cout<<ans<<endl;else cout<<"Impossible"<<endl;
}
【模拟+递归+位运算】POJ1753-Flip Game的更多相关文章
- [CSP-S模拟测试]:位运算(数学)
题目传送门(内部题72) 输入格式 输入文件$bit.in$ 每个输入文件包含$T$组测试数据.输入文件的第一行为一个整数$T$,表示数据组数.接下来$T$行,每行表示一组测试数据每组测试数据包括三个 ...
- Winner Winner【模拟、位运算】
Winner Winner 题目链接(点击) 题目描述 The FZU Code Carnival is a programming competetion hosted by the ACM-ICP ...
- UVa 818Cutting Chains (暴力dfs+位运算+二进制法)
题意:有 n 个圆环,其中有一些已经扣在一起了,现在要打开尽量少的环,使所有的环可以组成一条链. 析:刚开始看的时候,确实是不会啊....现在有点思路,但是还是差一点,方法也不够好,最后还是参考了网上 ...
- 为什么位运算可以实现加法(1、 不考虑进位的情况下位运算符中的异或^可以表示+号)(2、 位运算符中的与运算符&和左移运算符<<可以模拟加法中的进位)(3、位运算不仅可以做加法,还可以做其它的乘法减法等:计算机本质是二进制运算)
为什么位运算可以实现加法(1. 不考虑进位的情况下位运算符中的异或^可以表示+号)(2. 位运算符中的与运算符&和左移运算符<<可以模拟加法中的进位)(3.位运算不仅可以做加法,还 ...
- 神奇的Noip模拟试题 T3 科技节 位运算
3 科技节 (scifest.pas/.c/.cpp) [问题描述] 一年一度的科技节即将到来.同学们报名各项活动的名单交到了方克顺校长那,结果校长一看皱了眉头:这帮学生热情竟然如此高涨,每个人都报那 ...
- 【NOIP模拟题】“与”(位运算)
因为是与运算,所以我们可以贪心地每次找最高位的,将他们加入到新的序列中,然后每一次在这个新的序列继续找下一个位. 然后最后序列中任意两个的与运算的值都是一样的且是最大的. #include <c ...
- 模拟赛T5 : domino ——深搜+剪枝+位运算优化
这道题涉及的知识点有点多... 所以还是比较有意思的. domino 描述 迈克生日那天收到一张 N*N 的表格(1 ≤ N ≤ 2000),每个格子里有一个非 负整数(整数范围 0~1000),迈克 ...
- poj1753,Flip Game,ArrayDeque<Node>
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30449 Accepted: 13232 Descr ...
- js中的位运算
按位运算符是把操作数看作一系列单独的位,而不是一个数字值.所以在这之前,不得不提到什么是"位": 数值或字符在内存内都是被存储为0和 1的序列,每个0和1被称之为1个位,比如说10 ...
随机推荐
- 简述--构建React项目的几种方式
前言: 构建React项目的几种方式: 构建:create-react-app 快速脚手架 构建:generator-react-webpack 构建:webpack一步一步构建 1)构建:creat ...
- js 重置表单
//方法一document.getElementById("myform").reset(); //方法二 ].reset(); //方法三 使用input按钮 <input ...
- js 数组&字符串 去重
Array.prototype.unique1 = function() { var n = []; //一个新的临时数组 for(var i = 0; i < this.length; i++ ...
- mysql中的enum型
enum设置后 值只能是给出的值中的其中一个 mysql> create table enum(e enum('1','2','3','4','5','6','7','8','9','10')) ...
- Perl6 Bailador框架(6):获取用户输入
use v6; use Bailador; get '/' => sub { ' <html> <head><title></title>< ...
- Msfvenom学习总结-MSF反弹webshell
1. –p (- -payload-options) 添加载荷payload. 载荷这个东西比较多,这个软件就是根据对应的载荷payload生成对应平台下的后门,所以只有选对payload,再填 ...
- Django 1.10中文文档-第一个应用Part5-测试
本教程上接教程Part4. 前面已经建立一个网页投票应用,现在将为它创建一些自动化测试. 自动化测试简介 什么是自动化测试 测试是检查你的代码是否正常运行的行为.测试也分为不同的级别.有些测试可能是用 ...
- PHP配置Configure报错:Please reinstall the libzip distribution
PHP配置Configure报错:Please reinstall the libzip distribution 发生情景: php执行配置命令configure时,报如下错误: checking ...
- 1.Python3标准库--前戏
Python有一个很大的优势便是在于其拥有丰富的第三方库,可以解决很多很多问题.其实Python的标准库也是非常丰富的,今后我将介绍一下Python的标准库. 这个教程使用的书籍就叫做<Pyth ...
- java-增强for循环
public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); lis ...