由于数据规模不大,利用爆搜即可。第一次用位运算写的,但是转念一想应该用递归更加快,因为位运算没有剪枝啊(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的更多相关文章

  1. [CSP-S模拟测试]:位运算(数学)

    题目传送门(内部题72) 输入格式 输入文件$bit.in$ 每个输入文件包含$T$组测试数据.输入文件的第一行为一个整数$T$,表示数据组数.接下来$T$行,每行表示一组测试数据每组测试数据包括三个 ...

  2. Winner Winner【模拟、位运算】

    Winner Winner 题目链接(点击) 题目描述 The FZU Code Carnival is a programming competetion hosted by the ACM-ICP ...

  3. UVa 818Cutting Chains (暴力dfs+位运算+二进制法)

    题意:有 n 个圆环,其中有一些已经扣在一起了,现在要打开尽量少的环,使所有的环可以组成一条链. 析:刚开始看的时候,确实是不会啊....现在有点思路,但是还是差一点,方法也不够好,最后还是参考了网上 ...

  4. 为什么位运算可以实现加法(1、 不考虑进位的情况下位运算符中的异或^可以表示+号)(2、 位运算符中的与运算符&和左移运算符<<可以模拟加法中的进位)(3、位运算不仅可以做加法,还可以做其它的乘法减法等:计算机本质是二进制运算)

    为什么位运算可以实现加法(1. 不考虑进位的情况下位运算符中的异或^可以表示+号)(2. 位运算符中的与运算符&和左移运算符<<可以模拟加法中的进位)(3.位运算不仅可以做加法,还 ...

  5. 神奇的Noip模拟试题 T3 科技节 位运算

    3 科技节 (scifest.pas/.c/.cpp) [问题描述] 一年一度的科技节即将到来.同学们报名各项活动的名单交到了方克顺校长那,结果校长一看皱了眉头:这帮学生热情竟然如此高涨,每个人都报那 ...

  6. 【NOIP模拟题】“与”(位运算)

    因为是与运算,所以我们可以贪心地每次找最高位的,将他们加入到新的序列中,然后每一次在这个新的序列继续找下一个位. 然后最后序列中任意两个的与运算的值都是一样的且是最大的. #include <c ...

  7. 模拟赛T5 : domino ——深搜+剪枝+位运算优化

    这道题涉及的知识点有点多... 所以还是比较有意思的. domino 描述 迈克生日那天收到一张 N*N 的表格(1 ≤ N ≤ 2000),每个格子里有一个非 负整数(整数范围 0~1000),迈克 ...

  8. poj1753,Flip Game,ArrayDeque&lt;Node&gt;

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30449   Accepted: 13232 Descr ...

  9. js中的位运算

    按位运算符是把操作数看作一系列单独的位,而不是一个数字值.所以在这之前,不得不提到什么是"位": 数值或字符在内存内都是被存储为0和 1的序列,每个0和1被称之为1个位,比如说10 ...

随机推荐

  1. It is possible that this issue is resolved by uninstalling an existi

    使用真机连接Android Studio测试时出现这样的错误: 解决方法: 设置Android Studio 中Instant Run中的选项为不选中 根据以下路径,找到Instant Run中的选项 ...

  2. 完全教程 Aircrack-ng破解WEP、WPA-PSK加密利器

    其 实关于无线基础知识的内容还是挺多的,但是由于本书侧重于BT4自身工具使用的讲解,若是再仔细讲述这些外围的知识,这就好比讲述DNS工具时还要把 DNS服务器的类型.工作原理及配置讲述一遍一样,哈哈, ...

  3. xctf一道反序列化题

    题目地址:http://120.24.86.145:8006/test1/ 右键get源码: <?php $user = $_GET["txt"]; $file = $_GE ...

  4. thread线程栈size及局部变量最大可分配size【转】

    转自:http://blog.csdn.net/sunny04/article/details/46805261 版权声明:本文为博主原创文章,未经博主允许不得转载. 进程是操作系统的最小资源管理单元 ...

  5. .gitignore 文件添加或更新后规则无效的解决方案

    项目已经提交之后,突然想忽略某个文件或目录 A,于是在 .gitignore 里添加了忽略规则.但是提交(commit)之后,发现一旦修改了 A,git 同样会检测到 A 的变化(changes) , ...

  6. python实战===2017年30个惊艳的Python开源项目 (转)

    本文转自:http://www.sohu.com/a/216723120_115128 摘要:本文来自Mybridge,介绍了过去一年里30个惊艳的Python开源项目.点击每一个都可以在GitHub ...

  7. sql server查看创建表的代码,表定义

    1.查看建表语句在“对象资源管理器”中找到要导出的表,选中该表并单击右键,“编写表脚本为(S)”/“CREATE到(C)”/“新查询编辑器窗口”即可查看该表的建表语句.2.导出建表语句在“对象资源管理 ...

  8. FineReport——FS

    FR除了能够实现对报表等的二次开发,还能实现对决策系统的操作: FS.Trans.signOut() 退出决策平台系统 FS.tabPane._doCloseTab(FS.tabPane._getSe ...

  9. PIL处理图片信息

    最近遇到了图片处理的一些问题,python提供了一些库可以很方便地帮助我们解决这些问题,在这里把我这几天的学习总结一下. 一.提取图片的RGB值 1.非代码:如果只是为了提取某张图片或者某个像素点的R ...

  10. Html Css  练习

    一.  取消a链接的下划线 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...