POJ2531&&1416&&2676&&1129
搜索专题的最后一块了,也告别了这些老的东西了
接下来就是些全新的内容了啊!
这次的标签是简单搜索技巧和剪枝,也就是优化爆搜
当然,像Dancing links这样的玄学操作还是没有的
2531
题意:给你n个点,你可以把它们分成两组,求所有不同组别之间的点的边权和。
爆搜O(2^20*10)理论上也不会超时,但POJ的老爷机并不是Luogu,所以我们要剪枝
假设刚开始所有点默认都在0号集合(共0,1两个集合),那么对于一个点,先将它移到1号集合中,看看得到的边权和与之前相比是否减小。若减小了就剪枝。
一个小贪心,正确性显然
注意如果边权和与之前相比变大了仍然要枚举在0号集合的状况
CODE
#include<cstdio>
using namespace std;
const int N=25;
int a[N][N],n,ans;
bool vis[N];
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline void DFS(int now,int tot)
{
if (now>n) { ans=tot>ans?tot:ans; return; }
vis[now]=1;
int res=tot;
for (register int i=1;i<=n;++i)
if (vis[i]) res-=a[now][i]; else res+=a[now][i];
if (res>tot) DFS(now+1,res);
vis[now]=0; DFS(now+1,tot);
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j;
for (read(n),i=1;i<=n;++i)
for (j=1;j<=n;++j)
read(a[i][j]);
DFS(1,0);
printf("%d",ans);
return 0;
}
1416
有一个碎纸机,你可以扔进去一个数(不超过6位),你可以将它切割成几段,但这几段的和必须小于一个给出的target,输出可能的最接近target的值,无解输出error,多解输出rejected
DFS切割的部位,可以把数字预处理出来
剪枝:若当前的这种割法会超过target就不枚举
CODE
#include<cstdio>
#include<cstring>
using namespace std;
int m,n,num[10][10],sum[10],ans,kinds,cnt;
bool cut[10],c[10];
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline void write(int x)
{
if (x/10) write(x/10);
putchar(x%10+'0');
}
inline void init(int n)
{
if (n/10) init(n/10);
num[++cnt][1]=n%10;
}
inline void DFS(int now,int tot)
{
if (now>cnt)
{
if (ans==1e9) { ans=tot,kinds=1,memcpy(c,cut,sizeof(c)); return; }
if (tot==ans) ++kinds;
if (tot>ans) ans=tot,kinds=1,memcpy(c,cut,sizeof(c));
return;
}
if (tot+sum[cnt]-sum[now-1]>m) return;
for (register int i=now+1;i<=cnt+1;++i)
{
if (tot+num[now][i-now]>m) continue;
cut[i]=1; DFS(i,tot+num[now][i-now]); cut[i]=0;
}
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j;
read(m); read(n);
while (m||n)
{
cnt=kinds=0; ans=1e9;
memset(cut,0,sizeof(cut)); cut[1]=1;
init(n);
for (i=1;i<=cnt;++i)
{
sum[i]=sum[i-1]+num[i][1];
for (j=1;i+j-1<=cnt;++j)
num[i][j]=num[i][j-1]*10+num[i+j-1][1];
}
DFS(1,0);
if (ans==1e9) { puts("error"); read(m); read(n); continue; }
if (kinds>1) { puts("rejected"); read(m); read(n); continue; }
write(ans);
for (i=1;i<=cnt;++i)
{
if (c[i]) putchar(' ');
putchar(num[i][1]+'0');
}
putchar('\n'); read(m); read(n);
}
return 0;
}
2676
数独游戏,每一行,每一列,每一个宫格内的数字为1——9且均不重复
现在给你一个未完成的数独,输出一个它的合法解
这个更简单了,在爆搜的基础上直接剪去那些中途就冲突的情况即可
CODE
#include<iostream>
#include<cstring>
using namespace std;
const int N=15;
const int num[9][9]=
{
{1,1,1,2,2,2,3,3,3},
{1,1,1,2,2,2,3,3,3},
{1,1,1,2,2,2,3,3,3},
{4,4,4,5,5,5,6,6,6},
{4,4,4,5,5,5,6,6,6},
{4,4,4,5,5,5,6,6,6},
{7,7,7,8,8,8,9,9,9},
{7,7,7,8,8,8,9,9,9},
{7,7,7,8,8,8,9,9,9}
};
int a[N][N],n;
bool h[N][N],l[N][N],g[N][N],flag;
char ch;
inline void print(void)
{
for (register int i=1;i<=9;++i)
{
for (register int j=1;j<=9;++j)
cout<<a[i][j];
cout<<endl;
}
}
inline void DFS(int x,int y)
{
if (flag) return;
if (x>9) { print(); flag=1; return; }
int xx=x,yy=y;
if (++yy>9) yy=1,++xx;
if (a[x][y]) DFS(xx,yy); else
{
for (register int i=1;i<=9;++i)
{
if (h[x][i]||l[y][i]||g[num[x-1][y-1]][i]) continue;
a[x][y]=i; h[x][i]=l[y][i]=g[num[x-1][y-1]][i]=1;
DFS(xx,yy);
h[x][i]=l[y][i]=g[num[x-1][y-1]][i]=a[x][y]=0;
}
}
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j;
std::ios::sync_with_stdio(false);
cin>>n;
while (n--)
{
memset(h,0,sizeof(h));
memset(l,0,sizeof(l));
memset(g,0,sizeof(g));
for (i=1;i<=9;++i)
for (j=1;j<=9;++j)
{
cin>>ch; a[i][j]=ch-'0';
h[i][a[i][j]]=l[j][a[i][j]]=g[num[i-1][j-1]][a[i][j]]=1;
}
flag=0; DFS(1,1);
}
return 0;
}
1129
给你一个无向图,要求相邻的两个点的颜色不能重复,让你求最少用多少种颜色就可以将图染上色
爆搜即可,如果相邻的点已经有这种颜色就不选这种颜色。
但注意不管怎么样都要搜一下多加一种颜色的可能性
大坑点输出时注意channel的单复数
CODE
#include<cstdio>
#include<cstring>
using namespace std;
const int N=30;
struct edge
{
int to,next;
}e[N*N<<1];
int head[N],col[N],n,cnt,tot;
char s,t;
bool sign;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline void add(int x,int y)
{
e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
}
inline void write(int x)
{
if (x/10) write(x/10);
putchar(x%10+'0');
}
inline void print(void)
{
write(tot);
if (tot>1) puts(" channels needed."); else puts(" channel needed.");
}
inline void DFS(int now)
{
if (sign) return;
if (now>n) { print(); sign=1; return; }
for (register int i=1;i<=tot;++i)
{
bool flag=1;
for (register int j=head[now];j!=-1;j=e[j].next)
if (col[e[j].to]==i) { flag=0; break; }
if (flag) col[now]=i,DFS(now+1);
}
col[now]=++tot; DFS(now+1);
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j;
for (;;)
{
read(n); cnt=sign=tot=0;
memset(e,-1,sizeof(e));
memset(head,-1,sizeof(head));
memset(col,0,sizeof(col));
if (!n) break;
for (i=1;i<=n;++i)
{
s=tc(); t=tc(); t=tc();
while (t>='A'&&t<='Z') add(s-'A'+1,t-'A'+1),t=tc();
}
DFS(1);
}
return 0;
}
其实这次的题目普遍都是可行性剪枝,关于最优化剪枝,一般用A*的较多
POJ2531&&1416&&2676&&1129的更多相关文章
- 【转】POJ题目分类
初级:基本算法:枚举:1753 2965贪心:1328 2109 2586构造:3295模拟:1068 2632 1573 2993 2996 图:最短路径:1860 3259 1062 2253 1 ...
- POJ 题目分类(转载)
Log 2016-3-21 网上找的POJ分类,来源已经不清楚了.百度能百度到一大把.贴一份在博客上,鞭策自己刷题,不能偷懒!! 初期: 一.基本算法: (1)枚举. (poj1753,poj2965 ...
- (转)POJ题目分类
初期:一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. ...
- poj分类
初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. ( ...
- 转载 ACM训练计划
leetcode代码 利用堆栈:http://oj.leetcode.com/problems/evaluate-reverse-polish-notation/http://oj.leetcode. ...
- POJ题目分类(按初级\中级\高级等分类,有助于大家根据个人情况学习)
本文来自:http://www.cppblog.com/snowshine09/archive/2011/08/02/152272.spx 多版本的POJ分类 流传最广的一种分类: 初期: 一.基本算 ...
- POJ题目分类(转)
初期:一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. ...
- ACM学习
转:ACM大量习题题库 ACM大量习题题库 现在网上有许多题库,大多是可以在线评测,所以叫做Online Judge.除了USACO是为IOI准备外,其余几乎全部是大学的ACM竞赛题库. US ...
- POJ题目(转)
http://www.cnblogs.com/kuangbin/archive/2011/07/29/2120667.html 初期:一.基本算法: (1)枚举. (poj1753,poj29 ...
随机推荐
- Windows10+VS2017 用GLFW+GLAD 搭建OpenGL开发环境
本文参考:https://learnopengl-cn.github.io/ 一 下载GLFW(https://www.glfw.org/download.html) 和 GLAD(https:// ...
- Expo大作战(二十七)--expo sdk api之Util(expo自带工具类),tackSnapshotAsync,Svg,SQLite
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- 创建Filter类
1.Filter可认为是servlet的一种“加强版”,它主要用于对用户请求进行预处理,也可以对HttpServletresponse进行后处理,是个典型的处理链.Filter也可对用户请求生成响应, ...
- VMware部署ubuntu后开机提示piix4_smbus: Host SMBus controller not enabled!
在虚拟机部署ubuntu10.04-server,每次启动完成之后,出现“piix4_smbus0000:00:07.3: Host SMBus controller not enabled!”提示信 ...
- xp_readerrorlog与sp_readerrorlog
SQL SERVER 可以使用xp_readerrorlog 或者sp_readerrorlog来查看错误日志. xp_readerrorlog 一共有七个参数: 1. 存档编号 2. 日志类型(1为 ...
- 10分钟让你明白MySQL是如何利用索引的
一.前言 在MySQL中进行SQL优化的时候,经常会在一些情况下,对MySQL能否利用索引有一些迷惑. 譬如: MySQL 在遇到范围查询条件的时候就停止匹配了,那么到底是哪些范围条件? MySQL ...
- django直接操作MySQL,中文乱码
sql_insert = '''insert into sinfors_hvvms values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)''' c ...
- 向磁盘写入数据提示:No spac left on device通过df -h查看磁盘空间,发现没满,解决方法
初步判断应该有两种情况:一种是block满了,另一种情况就是inode耗尽了. 首先df -i 查看一下是否耗尽inode/block数量. 虚拟一块磁盘并格式化: dd if=/dev/zero o ...
- 在TortoiseSVN使用clean up
1.在[Cleanup]窗体中勾选中复选框[Clean up working copy status],选中该复选框表示解除锁定. 2.在[Cleanup]窗体中勾选中复选框[revert all c ...
- MySQL基础之 AND和OR运算符
AND和OR运算符 作用:用于基于一个以上的条件对记录进行过滤 用法:可在WHERE子句中把两个或多个条件结合在一起. AND:如果第一个条件和第二个条件都成立,才会显示一条记录 OR:如果第一个条件 ...