poj1020 搜索
来源:互联网 发布:反网络尖兵 编辑:程序博客网 时间:2024/05/22 18:00
如题:http://poj.org/problem?id=1020
Description
Input
Output
Sample Input
24 8 1 1 1 1 1 3 1 15 6 3 3 2 1 1 1
Sample Output
KHOOOOB!HUTUTU!
Source
一开始的思路是毫无剪枝的强行深搜,虽然知道应该会超,但还是试了试。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int need[20];
int map[200][200];
int cmp(int &a,int &b)
{
return a>b;
}
int judge(int x,int y,int pos)
{
int i,j;
if(x+need[pos]-1>n||y+need[pos]-1>n)
return 0;
for(i=x;i<x+need[pos];i++)
for(j=y;j<y+need[pos];j++)
if(map[i][j])
return 0;
return 1;
}
int dfs(int pos) //将第pos个小正方形放进
{
if(pos==m)
{
return 1;
}
int i,j,k,l;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(judge(i,j,pos))
{
for(k=i;k<i+need[pos];k++)
for(l=j;l<j+need[pos];l++)
map[k][l]=1;
if(dfs(pos+1))
return 1;
for(k=i;k<i+need[pos];k++)
for(l=j;l<j+need[pos];l++)
map[k][l]=0;
}
}
return 0;
}
int main()
{
// freopen("C:\\1.txt","r",stdin);
int t;
cin>>t;
int i;
while(t--)
{
scanf("%d",&n);
scanf("%d",&m);
int s=0;
for(i=0;i<m;i++)
{
scanf("%d",&need[i]);
s+=need[i]*need[i];
}
if(s!=n*n)
{
printf("HUTUTU!\n");
continue;
}
sort(need,need+m,cmp);
memset(map,0,sizeof(map));
if(dfs(0))
printf("KHOOOOB!\n");
else
printf("HUTUTU!\n");
}
return 0;
}
之后看了别人的报告,受益匪浅。
每一次找到一个合适的位置,放进这个位置能放的最大一个方块。
col[i]数组代表第i列里有单位为1的蛋糕块的数量。
放蛋糕的方法:从左到右扫描出列,单位蛋糕最少的那一列,然后选择一个能放入的尽量大的放块放入。小方块最后放。
通过col数组和一种放方块的正确方法大大减少了搜索的复杂度。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
int sizenum[11];
int col[200];
int dfs(int num) //已经装入的蛋糕数量。满足每次选一个最大的装入。从
{
if(num==m)
return 1;
int mincol=0;
int min=200;
int i,j;
for(i=1;i<=n;i++)
{
if(col[i]<min)
{
min=col[i];
mincol=i;
}
}
for(i=10;i>=1;i--)
{
if(sizenum[i]&&n-min>=i&&n-mincol+1>=i)
{
int w=1;
for(j=mincol+1;j<mincol+i;j++)
{
if(col[j]<=min)
{
w++;
continue;
}
break; //不连续.
}
if(w>=i)
{
sizenum[i]--;
for(j=mincol;j<mincol+i;j++)
col[j]+=i;
if(dfs(num+1))
return 1;
sizenum[i]++;
for(j=mincol;j<mincol+i;j++)
col[j]-=i;
}
}
}
return 0;
}
int main()
{
// freopen("C:\\1.txt","r",stdin);
int t;
cin>>t;
int i;
while(t--)
{
memset(sizenum,0,sizeof(sizenum));
memset(col,0,sizeof(col));
cin>>n;
cin>>m;
int s=0;
for(i=0;i<m;i++)
{
int size;
scanf("%d",&size);
sizenum[size]++;
s+=size*size;
}
if(s!=n*n)
{
printf("HUTUTU!\n");
continue;
}
if(dfs(0))
printf("KHOOOOB!\n");
else
printf("HUTUTU!\n");
}
return 0;
}
- poj1020 搜索
- poj1020 Anniversary Cake 搜索
- poj1020
- poj1020
- poj1020
- poj1020--DFS
- poj1020 dfs
- poj1020--Anniversary Cake题解
- poj1020 cake解题报告
- OJ-POJ1020-DFS
- POJ1020 分蛋糕
- poj1020 暴搜暴的很有水平~
- poj1020分蛋糕(用一堆小正方形拼成一个大正方形)
- poj1020(非常经典的dfs,易理解,难写代码)
- 搜索
- 搜索
- 搜索
- 搜索
- Oracle RAC的VIP和SCAN IP
- float 在 CUDA
- 查看Androi的appPackage和Activity的多种方法
- 第三章第三十题杨辉三角求某行某列的数
- Java语言绘画—没有尾巴的小乌龟
- poj1020 搜索
- BZOJ 3994 [SDOI2015]约数个数和
- 台湾--电话正则表达式
- IE7以下不兼容JS的onsubmit方法
- 1.函数返回值的应用
- 使用 typedef 简化函数指针
- 解决存到数据库里中文乱码问题
- 【BZOJ2961】【Codevs2003】共点圆
- 澳门--电话正则表达式