0x21 剪枝
这一章真是心态崩,剪枝太玄学啦,特别是那个搜索顺序我靠真的。。。
poj1011 枚举答案,搜索记录当前到第几根木棒。 剪枝:1、从大到小排序 2、排除等效,这个感觉还行,就是木棒按大小顺序进去,去除顺序不同的相同的情况,相同的木棒也是不用管的。 好的前面这些都可以想,关键是第三个,拼接第一个失败就全部重来。这个真是没想到
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; int n,L,C,c[];
bool cmp(int x,int y){return x>y;}
bool v[];
bool dfs(int k,int len,int last)
{
if(k==C+)return true;
if(len==L)return dfs(k+,,); int fail=;
for(int i=last+;i<=n;i++)
{
if(v[i]==false&&len+c[i]<=L&&c[i]!=fail)
{
v[i]=true;
if(dfs(k,len+c[i],i))return true;
v[i]=false;
fail=c[i];
if(len==)return false;
}
}
return false;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==)break; int sum=;
for(int i=;i<=n;i++)
scanf("%d",&c[i]), sum+=c[i];
sort(c+,c+n+,cmp); int mmin=;
for(int i=;i*i<=sum;i++)
if(sum%i==)
{
if(i<mmin)
{
L=i, C=sum/i;
memset(v,false,sizeof(v));
if(dfs(,,)==true)mmin=min(mmin,i);
}
if(sum/i<mmin&&i*i!=sum)
{
L=sum/i, C=i;
memset(v,false,sizeof(v));
if(dfs(,,)==true)mmin=min(mmin,sum/i);
}
}
printf("%d\n",mmin);
}
return ;
}
poj1011
poj1190 这题简直就是剪枝的代表作了。。。我可以算是想出了1.5+2??个trick,但是这题整整五个剪枝啊!!!
1、大小,看到这个我都快条件反射了,管他有的没的倒序就是没错的
2、上下界,这个我想得还要复杂一点,导致有点难算,lyd就很暴力了直接开根
3、4、对于体积和表面积,到达目标的最小花费+当前花费比限制、当前最小花费大,那么就剪掉。我纠结了一会为啥一个叫可行性剪枝一个叫最优性剪枝,是因为体积是确定的而表面积是要求的
5、最***玄学的就是这个不等式了,上面全部的体积可以表示成sigema(1~dep-1)h[i]*r[i]^2,表面积就是2*sigema(1~dep-1)h[i]*r[i], 假设当前已经的体积为V
2*sigema(1~dep-1)h[i]*r[i] = 2/r[dep]*sigema(1~dep-1)h[i]*r[i]*r[dep] >= 2/r[dep]*sigema(1~dep-1)h[i]*r[i]*r[i] = 2*(N-V)/r[dep] 这个时候又可以判表面积。。。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; int N,m,mmin,r[],h[];
int minV[],minS[];
void dfs(int k,int V,int S)
{
if(minV[k]+V>N)return ;
if(minS[k]+S>mmin)return ;
if(*(N-V)/r[k+]+S>mmin)return ;
if(k==)
{
if(minV[k]+V==N)mmin=min(mmin,S);
return ;
} int Rli=min( int(sqrt(double(N-V+))) , r[k+]- );
for(int R=Rli;R>=k;R--)
{
int Hli=min( (N-V)/(R*R) , h[k+]- );
for(int H=Hli;H>=k;H--)
{
r[k]=R;h[k]=H;
dfs(k-,V+R*R*H,S+*R*H+((k==m)?R*R:));
}
}
}
int main()
{
scanf("%d%d",&N,&m);
for(int i=;i<=m;i++)
minV[i]=i*i*i+minV[i-], minS[i]=*i*i+minS[i-]; mmin=;
r[m+]=h[m+]=;
dfs(m,,);
printf("%d\n",mmin);
return ;
}
poj1190
poj3076 状压,判点,判字母,绝望,留坟
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<bitset>
using namespace std; int cnt;
char ss[][],sc[][][];
bitset<>mp[][],tt[][][],ts[][][];
void init()
{
memset(mp,,sizeof(mp));
for(int j=;j<=;j++)//行
{
int zt=;
for(int i=;i<=;i++)
if(ss[i][j]!='-')
zt|=(<<(ss[i][j]-'A'));
for(int i=;i<=;i++) mp[i][j]|=zt;
}
for(int i=;i<=;i++)//列
{
int zt=;
for(int j=;j<=;j++)
if(ss[i][j]!='-')
zt|=(<<(ss[i][j]-'A'));
for(int j=;j<=;j++) mp[i][j]|=zt;
}
for(int i=;i<=;i+=)
for(int j=;j<=;j+=)
{
int zt=;
for(int k=;k<=;k++)
for(int l=;l<=;l++)
if(ss[i+k-][j+l-]!='-')
zt|=(<<(ss[i+k-][j+l-]-'A'));
for(int k=;k<=;k++)
for(int l=;l<=;l++)
mp[i+k-][j+l-]|=zt;
} cnt=;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
if(ss[i][j]=='-')cnt++;
mp[i][j].flip();
}
} bitset<>p;bool v[];
bool check()
{
for(int i=;i<=;i++)
for(int j=;j<=;j++)
if(mp[i][j]==&&ss[i][j]=='-')return false; for(int i=;i<=;i++)
{
p.reset();memset(v,false,sizeof(v));
for(int j=;j<=;j++)
{
if(ss[i][j]!='-')v[ss[i][j]-'A']=true;
else p|=mp[i][j];
}
for(int o=;o<=;o++)
if(p[o]==&&v[o]==false)return false;
}
for(int j=;j<=;j++)
{
p.reset();
for(int i=;i<=;i++)
{
if(ss[i][j]!='-')v[ss[i][j]-'A']=true;
else p|=mp[i][j];
}
for(int o=;o<=;o++)
if(p[o]==&&v[o]==false)return false;
}
for(int i=;i<=;i+=)
for(int j=;j<=;j+=)
{
p.reset();memset(v,false,sizeof(v));
for(int k=;k<=;k++)
for(int l=;l<=;l++)
{
if(ss[i+k-][j+l-]!='-')v[ss[i+k-][j+l-]-'A']=true;
else p|=mp[i+k-][j+l-];
}
for(int o=;o<=;o++)
if(p[o]==&&v[o]==false)return false;
}
return true;
}
void influence(int x,int y)
{
int o=ss[x][y]-'A';
for(int j=;j<=;j++)mp[x][j][o]=;
for(int i=;i<=;i++)mp[i][y][o]=; int i=((x-)/)*+,j=((y-)/)*+;
for(int k=;k<=;k++)
for(int l=;l<=;l++)
mp[i+k-][j+l-][o]=;
}
bool bk;
void dfs(int k,int dep)
{
if(bk==true)return ; memcpy(ts[dep],mp,sizeof(ts[dep]));
memcpy(sc[dep],ss,sizeof(sc[dep]));
bool qwq=true;
while(qwq)
{
qwq=false;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
if(ss[i][j]=='-'&&mp[i][j].count()==)
{
k--;qwq=true;
for(int o=;o<=;o++)
if(mp[i][j][o]==)
{
ss[i][j]='A'+o;
influence(i,j);
break;
}
}
}
for(int o=;o<=;o++)
{
for(int i=;i<=;i++)
{
int u=,jj;
for(int j=;j<=;j++)
if(mp[i][j][o]==)
{
u++;jj=j;
if(u==)break;
}
if(u==)
{
ss[i][jj]='A'+o;
influence(i,jj);
}
}
for(int j=;j<=;j++)
{
int u=,ii;
for(int i=;i<=;i++)
if(mp[i][j][o]==)
{
u++;ii=i;
if(u==)break;
}
if(u==)
{
ss[ii][j]='A'+o;
influence(ii,j);
}
}
for(int i=;i<=;i+=)
for(int j=;j<=;j+=)
{
int u=,ii,jj;
for(int k=;k<=;k++)
for(int l=;l<=;l++)
{
if(mp[i+k-][j+l-][o]==)
{
u++;ii=i;jj=j;
if(u==)break;
}
}
if(u==)
{
ss[ii][jj]='A'+o;
influence(ii,jj);
}
}
}
}//必定赋值
if(!check())
{
memcpy(mp,ts[dep],sizeof(mp));
memcpy(ss,sc[dep],sizeof(ss));
return ;
} if(k==)
{
bk=true;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)printf("%c",ss[i][j]);
printf("\n");
}
return ;
} int cc=,nx,ny;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
if(ss[i][j]=='-'&&mp[i][j].count()<cc)
{
cc=mp[i][j].count();
nx=i,ny=j;
}
for(int o=;o<=;o++)
if(mp[nx][ny][o]==)
{
memcpy(tt[dep],mp,sizeof(tt[dep]));
ss[nx][ny]='A'+o; influence(nx,ny);
if(check())
dfs(k-,dep+); ss[nx][ny]='-';
memcpy(mp,tt[dep],sizeof(mp));
} memcpy(mp,ts[dep],sizeof(mp));
memcpy(ss,sc[dep],sizeof(ss));
}
int main()
{
for(int i=;i<=;i++)scanf("%s",ss[i]+);
init(); bk=false;dfs(cnt,);
return ;
}
poj3076(TLE)
0x21 剪枝的更多相关文章
- α-β剪枝算法的java语言实现(非常实用)
利用α-β剪枝算法,对下图所示的博弈树进行搜索,搜索得到根节点选择的走步,以及没有必要进行评估的节点,并求出给出在何处发生了剪枝,以及剪枝的类型(属于α剪枝还是β剪枝). 注:□表示MIN节点:○表示 ...
- Sicily 1153: 马的周游问题(DFS+剪枝)
这道题没有找到一条回路,所以不能跟1152一样用数组储存后输出.我采用的方法是DFS加剪枝,直接DFS搜索会超时,优化的方法是在搜索是优先走出度小的路径,比如move1和move2都可以走,但是如走了 ...
- HDU5887 Herbs Gathering(2016青岛网络赛 搜索 剪枝)
背包问题,由于数据大不容易dp,改为剪枝,先按性价比排序,若剩下的背包空间都以最高性价比选时不会比已找到的最优解更好时则剪枝,即 if(val + (LD)pk[d].val / (LD)pk[d]. ...
- HDU5937 Equation(DFS + 剪枝)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5937 Description Little Ruins is a studious boy, ...
- alpha-beta剪枝搜索
•一种基于剪枝( α-βcut-off)的深度优先搜索(depth-first search). •将走棋方定为MAX方,因为它选择着法时总是对其子节点的评估值取极大值,即选择对自己最为有利的着法: ...
- POJ1190生日蛋糕[DFS 剪枝]
生日蛋糕 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 18236 Accepted: 6497 Description ...
- *HDU1455 DFS剪枝
Sticks Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- HDU1010 DFS+剪枝
Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- HDU 5113 dfs剪枝
题意:告诉格子规格,颜色个数,以及每个颜色能涂得格子数目,问是否能够实现相邻两个格子的颜色数目不相同. 分析:因为数据很小,格子最多是5 * 5大小的,因此可以dfs.TLE了一次之后开始剪枝,31m ...
随机推荐
- Scrapy中的核心工作流程以及POST请求
五大核心组件工作流程 post请求发送 递归爬取 五大核心组件工作流程 引擎(Scrapy)用来处理整个系统的数据流处理, 触发事务(框架核心) 调度器(Scheduler)用来接受引擎发过来的请求, ...
- (转载)Android 方法数超过64k、编译OOM、编译过慢解决方案。
Android 方法数超过64k.编译OOM.编译过慢解决方案. 目前将项目中的leancloud的即时通讯改为环信的即时通讯.当引入easeui的时候 出现方法数超过上限的问题. 搜索一下问题, ...
- Fragment_动态加载
1.新建Fragment的XML布局文件. 2.在activity.xml中添加需要加载Fragment.列如: <?xml version="1.0" encoding=& ...
- SQL SERVER数据库状态
一个SQL SERVER数据库会处于很多种状态,例如 ONLINE .RESTORING .RECOVERING .RECOVERY_PENDING .SUSPECT.EMERGENCY .OFFL ...
- npm一点点
写在开头 要抓紧学习了,不然要遭... 月底之前有大量东西要学习,干 npm 包管理工具 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从NPM服务器下载并安装别人编写的命令行程序 ...
- 工欲善其事必先利其器之windows篇
Windows是我们最常用的系统,下面就让我们重新认识一下Windows有哪些可以让我们提高工作效率的快捷键以及部分技巧,,以及在外行看来可以看起来逼格高的技巧! 1.Windows最实用,最常用的快 ...
- MVC 接收文件
[HttpPost] public ActionResult Layedit() { var files = Request.Files; //获得所上传的所有文件 ) { HttpPostedFil ...
- Chernobyl’ Eagle on a Roof(鹰蛋坚固度)
链接 Chernobyl’ Eagle on a Roof 题意 引用论文题意:有一堆共 M 个鹰蛋,一位教授想研究这些鹰蛋的坚硬度 E.他是通过不断从一幢 N 层的楼上向下扔鹰蛋来确定 E 的.当鹰 ...
- 【深入理解Java虚拟机】自动内存管理机制——垃圾回收机制
Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...
- [GSS5] Can you answer these queries V
大力讨论. luogu上交spoj的题卡的一比... 难受 wa了好几次,原因大概首先求的是非空区间,不能乱和0取max,第二点是求无相交的解时,在两段求lmx和rmx的时候可以取max(0). 区间 ...