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 ...
随机推荐
- 几道leetcode不会做的题目
1.set没有back()函数,今天想到用这个,才发现没有. 2. tuple的initialize_list construct好像不能使用,其实之前没使用过tuple,都是pair,复杂一点的自己 ...
- A - Antipalindrome
Problem description A string is a palindrome if it reads the same from the left to the right and fro ...
- Hadoop MapReduce编程 API入门系列之join(二十六)(未完)
不多说,直接上代码. 天气记录数据库 Station ID Timestamp Temperature 气象站数据库 Station ID Station Name 气象站和天气记录合并之后的示意图如 ...
- 大白话理解this
日常开发中,我们经常用到this.一开始常会用一种感觉去判断this的指向,当遇到复杂的函数调用时,就分不清this的指向. 今天我们来由浅入深来学习下. function family1(){ va ...
- Android GoogleMap 谷歌地图从零开始
说明 由于国内使用v2最新的谷歌地图有很多限制,所有如果要在真机上测试运行要做一些准备 准备1: vpn必不可少啦 推荐cloud vpn或者betternet都是不错的免费vpn 准备2: 由于最新 ...
- (转载)activity外部调用startActivity的new task异常解析
activity外部调用startActivity的new task异常解析 泡在网上的日子 / 文 发表于2013-09-07 12:45 第1314次阅读 异常,android,activity ...
- Win10 UWP Tile Generator
图标生成器 https://marketplace.visualstudio.com/items?itemName=shenchauhan.UWPTileGenerator 备份地址: http:// ...
- CentOS LiveCD、LiveDVD、BinDVD、netinstall、minimal版区别在哪里
BinDVD版——就是普通安装版,需安装到计算机硬盘才能用,bin一般都比较大,而且包含大量的常用软件,安装时无需再在线下载(大部分情况). minimal版——这个镜像文件用于安装一个非常基本的 C ...
- Nginx+php-fpm 502 504问题
常出现502,504错误 思路: 增大nginx与php-fpm通信时的缓存文件大小与个数 静态绑定5个php-fpm进程,减少频率启动进程的开销 利用sock文件代替tcp端口通信 解决办法: 调整 ...
- js中标签字符串的拼接
//1.用单双引号拼接 var valueDemo = "111"; var htmlStrs1 = '<option selected="selected&quo ...