您的位置:首页 > 其它

HDOJ5113

2016-05-02 19:06 183 查看
搜索题,不好好写会超时的搜索题

其实如果归类到搜索,弱觉得不是特别恰当。搜索只是为了得到某一个可行解,本质上的思路是数学上的想法和构造的解法

http://acm.hdu.edu.cn/showproblem.php?pid=5113

看到Special Judge想到多解的深搜是很正常的,有没有想过去构造合法解呢?

题意:n*m的矩阵,k种颜色,每种颜色a【i】个,问是否有方案,使得n*m的矩阵中,每个格子涂上与周围四个不相同的颜色,而且恰好把颜色使用完?

由于n和m都很小,考虑到简单的深搜是肯定没有问题的?

那么如何搜?先看个超时代码:戳我看超时代码

为什么会超时呢?因为深搜退完再进的情况可能出现了很多次

避免超时,只需要一句话:sort!

对各种颜色按照从大到小的方式排序,一个是避免超时,一个是从构造性的原理来解释:

只要最多的颜色数量不超过总数量即n*m的一半,那么是肯定有解的

最特殊的情况无非是这种:

4 4 2

8 8

即4*4的矩阵中16个格子,两种颜色

所以相互间隔开来就好

1 2 1 2

2 1 2 1

1 2 1 2

2 1 2 1

相当于构造一个矩阵,相邻数字均不相同

充要条件就是最多的颜色数量不超过总数量即n*m的一半

可以比较,AC代码与TLE代码差别非常小,但是数学和构造的思想在代码中无法体现,只能体现在思维中

int t,n,m,k;
struct node{
int num,pos;
}data[30];
int mp[10][10];

void Print(){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
printf("%d%c",mp[i][j],j==m?'\n':' ');
}

bool dfs(int x,int y){
if (x==n+1) return true;
for(int i=1;i<=k;i++)//选择哪一种颜色
if (data[i].num){
if (mp[x-1][y]!=data[i].pos&&mp[x][y-1]!=data[i].pos){
//为什么这儿不需要考虑出矩形
//因为外围有一圈以0作为边界的墙
//从左往右,从上往下涂色即可
data[i].num--;
mp[x][y]=data[i].pos;
if (y+1<=m){
if (dfs(x,y+1)) return true;
}
else if (dfs(x+1,1)) return true;
data[i].num++;
}
}
return false;
}

int cmp(node a,node b){
if (a.num!=b.num) return a.num>b.num;
return a.pos<b.pos;
}

int main(){
//input;
scanf("%d",&t);
for(int Case=1;Case<=t;Case++){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++){
scanf("%d",&data[i].num);
data[i].pos=i;
}
sort(data+1,data+k+1,cmp);
//为啥要排序?
//排序一个是为了不超时,一个是为了得到最多的颜色值
printf("Case #%d:\n",Case);
//脑洞题:
//如果最多的颜色不超过一半
//那么选一个最多的,选一个其他的,全部隔开就好了
//所以这个题并不是个搜索
//是个数学上的构造
if (data[1].num>(m*n+1)/2){
cout<<"NO"<<endl;
continue;
}
cout<<"YES"<<endl;
dfs(1,1);
Print();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: