POJ3185 The Water Bowls(反转法or dfs 爆搜)
题目大意: 奶牛有20只碗摆成一排,用鼻子顶某只碗的话,包括左右两只在内的一共三只碗会反向,现在给出碗的初始状态,问至少要用鼻子顶多少次才能使所有碗都朝上
一开始试了一下dfs,由于对dfs还是不太熟悉,先是用了一个数组b[i]来储存翻转后的状态,后来发现这个搜索的状态虽然类似背包,要么翻转,要么不翻转,但是翻转某个碗以后会对其他的也造成影响,所以这样这样做就错了,可以只用原来的数组就ok了
在上述问题解决后,又因为胡乱剪枝导致wa了几次,一开始我想先对a[0]和a[19]进行判断是否为1,来确定是否需要翻转,这样的话a[19]那儿的1可能是翻转后形成的,这是进行翻转就回不到原来的状态,导致没法遍历2^n而wa,同时,对a[0]是否为1的判断也是错的,因为a[0]等于1时也可以通过翻转a[1]来实现a[0]=0的要求,a[19]=1也可翻转下一次的a[18].
不用任何优化顶多2^20(10的6次方左右),也可以过,我最后是250ms左右过的.
dfs代码:(毕竟dfs的题做的比较少,也就先用dfs来练手了)(先翻转再翻回来的dfs才是对的)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define in(n) scanf("%d",&(n))
#define in2(x1,x2) scanf("%d%d",&(x1),&(x2))
#define inll(n) scanf("%I64d",&(n))
#define inll2(x1,x2) scanf("%I64d%I64d",&(x1),&(x2))
#define inlld(n) scanf("%lld",&(n))
#define inlld2(x1,x2) scanf("%lld%lld",&(x1),&(x2))
#define inf(n) scanf("%f",&(n))
#define inf2(x1,x2) scanf("%f%f",&(x1),&(x2))
#define inlf(n) scanf("%lf",&(n))
#define inlf2(x1,x2) scanf("%lf%lf",&(x1),&(x2))
#define inc(str) scanf("%c",&(str))
#define ins(str) scanf("%s",(str))
#define out(x) printf("%d\n",(x))
#define out2(x1,x2) printf("%d %d\n",(x1),(x2))
#define outf(x) printf("%f\n",(x))
#define outlf(x) printf("%lf\n",(x))
#define outlf2(x1,x2) printf("%lf %lf\n",(x1),(x2));
#define outll(x) printf("%I64d\n",(x))
#define outlld(x) printf("%lld\n",(x))
#define outc(str) printf("%c\n",(str))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define mem(X,Y) memset(X,Y,sizeof(X));
typedef vector<int> vec;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={,,-,},dy[]={,,,-};
const int INF=0x3f3f3f3f;
const ll mod=1e9+;
ll powmod(ll a,ll b) {ll res=;a%=mod;for(;b;b>>=){if(b&)res=res*a%mod;a=a*a%mod;}return res;}
const bool AC=true; int a[],b[],ans;
bool flag;
void dfs(int i,int cnt){
if(i==){
flag=true;
rep(j,,){
if(a[j]==) {
flag=false;
break;
}
}
if(flag){
ans=min(ans,cnt);
}
return;
}
else if(i==){
a[i]=!a[i];
a[i+]=!a[i+];
dfs(i+,cnt+);
a[i]=!a[i];
a[i+]=!a[i+];
dfs(i+,cnt); //此处也不用判断是否为1来剪枝,否则会wa
}
else if(i==){
a[i]=!a[i];
a[i-]=!a[i-];
dfs(i+,cnt+);
a[i]=!a[i];
a[i-]=!a[i-];
dfs(i+,cnt); //不要乱剪枝,否则翻转不回来
}
else{
a[i]=!a[i];
a[i-]=!a[i-];
a[i+]=!a[i+];
dfs(i+,cnt+);//先翻转,再翻回来
a[i]=!a[i];
a[i-]=!a[i-];
a[i+]=!a[i+];
dfs(i+,cnt);
}
return ;
}
int main(){
rep(i,,) {
in(a[i]);
}
ans=INF;
dfs(,);
out(ans);
return ;
}
下面是反转法:考虑某个碗,翻转下一个碗.
如果某个碗是0,则这个碗不需要考虑,继续考虑下一个碗,不断向前推进区间;
如果某个碗是1,则必须翻转下一个碗,继续考虑下一个碗,不断向前推进区间;
这样复杂度就是O(n),类似尺取法的思想;
从对称性的角度考虑问题
wa的注意了,不要通过判断a[0]=0来确定是否需要反转a[0],这样是错的如下面的情况: 0 0 1 0 0 0 0 0.....后面全是0,这时如果反转a[0]需要2步,不翻转a[0]需要12步(因为这个wa了n次),
所以不管a[0]为什么值都要尝试一下是否需要反转a[0],从对称性来看,从左向右翻转,a[19]要么翻转,要么不翻转,
所以翻转法有两种实现方式:从左向右翻转两次(反转a[0]或者不反转a[0])
从左向右翻转一次(不翻转a[0]),再从右向左翻转一次(不翻转a[19]);(让某个碗翻转的方式有两种)
从左向右翻转两次(反转a[0]或者不反转a[0])
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[],b[];
void turn(int i){
b[i-]^=;
b[i]^=;
if(i<) b[i+]^=;
}
int main(){
int cnt1=,cnt2=;
for(int i=;i<;i++)
scanf("%d",&a[i]);
//反转b[0];
memcpy(b,a,sizeof(a));
b[]^=;
b[]^=;
cnt1++; //此处要加1
for(int i=;i<;i++){
if(b[i]){
turn(i+);//考虑某个碗,反转其后面的碗
cnt1++;
}
}
if(b[]) cnt1=0x3f3f3f3f;
//不反转b[0];
memcpy(b,a,sizeof(a));
for(int i=;i<;i++){
if(b[i]){
turn(i+);//考虑某个碗,反转其后面的碗
cnt2++;
}
}
if(b[]) cnt2=0x3f3f3f3f;
printf("%d\n",min(cnt1,cnt2));
return ;
}
从左向右翻转一次(不翻转a[0]),再从右向左翻转一次(不翻转a[19]);
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[],b[];
void turn1(int i){
b[i-]^=;
b[i]^=;
if(i<) b[i+]^=;
}
void turn2(int i){
a[i+]^=;
a[i]^=;
if(i>) a[i-]^=;
}
int main(){
int cnt1=,cnt2=;
for(int i=;i<;i++)
scanf("%d",&a[i]);
memcpy(b,a,sizeof(a));
for(int i=;i<;i++){
if(b[i]){
turn1(i+);//考虑某个碗,反转其后面的碗
cnt1++;
}
}
if(b[]) cnt1=0x3f3f3f3f;
for(int i=;i>;i--){
if(a[i]){
turn2(i-);//考虑某个碗,反转其前面的碗
cnt2++;
}
}
if(a[]) cnt2=0x3f3f3f3f;
printf("%d\n",min(cnt1,cnt2));
return ;
}
POJ3185 The Water Bowls(反转法or dfs 爆搜)的更多相关文章
- HDU 4403 A very hard Aoshu problem(dfs爆搜)
http://acm.hdu.edu.cn/showproblem.php?pid=4403 题意: 给出一串数字,在里面添加一个等号和多个+号,使得等式成立,问有多少种不同的式子. 思路: 数据量比 ...
- POJ3185 The Water Bowls 反转(开关)
Description The cows have a line of 20 water bowls from which they drink. The bowls can be either ri ...
- [Gauss]POJ3185 The Water Bowls
题意:反正就是要给的一串01的变成全0 能影响自己和左右 最少需要几步 01方程组 异或解 ][]; // 增广矩阵 ]; // 解 ]; // 标记是否为自由未知量 int n; void debu ...
- 【BZOJ-1060】时态同步 树形DP (DFS爆搜)
1060: [ZJOI2007]时态同步 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2101 Solved: 595[Submit][Statu ...
- hdu 5506 GT and set(dfs爆搜)
Problem Description You are given N sets.The i−th set has Ai numbers.You should divide the sets into ...
- 火车进栈(进出栈的模拟,dfs爆搜)
这里有n列火车将要进站再出站,但是,每列火车只有1节,那就是车头. 这n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从 ...
- hdu 4770(枚举 + dfs爆搜)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4770 思路:由于最多只有15个".",可以直接枚举放置的位置,然后判断是否能够全部 ...
- Ancient Go---hdu5546(dfs爆搜CCPC题目)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5546 题意就是两个人下围棋,问在下一颗x是否能杀死o,'.'是空位子: 枚举所有的点,判断是否合法即可 ...
- 【csp模拟赛2】 爆搜 方格加数
[题目描述] xyz1048576正在玩一个关于矩阵的游戏. 一个n*m的矩阵,矩阵中每个数都是[1,12]内的整数.你可以执行下列两个操作任意多次: (1)指定一行,将该行所有数字+1. (2)指定 ...
随机推荐
- 通过redis的monitor命令排除故障
项目里有10台服务器都在一个刀箱里,其中一台是redis缓存服务器,另外的是app服务器.通过监控发现这个刀箱的流量750M,其中缓存服务器的流量达105M,这么高的流量已经造成其它项目的服务器网络延 ...
- Profile GPU rendering
自Android 4.1引入了“Profile GPU rendering”这个开发工具以帮助分析应用程序性能并并精确定位渲染问题,Android 4.3增加了可视效果:On screen as ba ...
- wxsqlite3的加密模块单独编译
其实就是个编译过程,so easy,只是网上的方法各种,而且不是最新的,所以自己琢磨了. 1.从sqlite网站下载sqlite-amalgamation-xxx和sqlite-dll-win32-x ...
- linux内网机器访问外网代理设置squid
公司一般出于安全考虑, 在同一局域网中只有一台机器可以访问外网,运维进行了整体的限制, 但是在后面的工作中,需要在机器上安装一些软件,及命令,所以其他的机器需要访问外网来简化工作, 但又不能打乱原有运 ...
- listview 遇到问题java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
开发的时候 遇到 java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0 这个异常有时候会有,有时候正常 不太好捕捉 猜测 已经 ...
- ionic2 干货
亲爱的程序员童鞋 分享干货啦 最近在研究ionic2 ,公司也在用ionic2 和typescript,angular2以及cordova做混编APP 我的博客随笔都是随性写的,做了某个功能就想分享一 ...
- Jinja2模版语言自定义filter的使用
Jinja2模版语言,自带有一些filter,能够在前端的模版中控制数据按照相应的方式显示.比如以下两种filter,分别能在前端控制数字的近似精度显示和根据字符串长度补齐: round(value, ...
- 用PHP迭代器来实现一个斐波纳契数列(转)
斐波纳契数列通常做法是用递归实现,当然还有其它的方法.这里现学现卖,用PHP的迭代器来实现一个斐波纳契数列,几乎没有什么难度,只是把类里的next()方法重写了一次.注释已经写到代码中,也是相当好理解 ...
- PHP安全编程:会话数据注入 比会话劫持更强大的攻击(转)
一个与会话暴露类似的问题是会话注入.此类攻击是基于你的WEB服务器除了对会话存储目录有读取权限外,还有写入权限.因此,存在着编写一段允许其他用户添加,编辑或删除会话的脚本的可能.下例显示了一个允许用户 ...
- Linux 开机自检的设置(tune2fs和fsck)
tune2fs和fsck的用法 tune2fs--调整ext2/ext3文件系统特性的工具. -l <device> 查看文件系统信息 -c <count> 设置强制自检的 ...