搜索题,不好好写会超时的搜索题
其实如果归类到搜索,弱觉得不是特别恰当。搜索只是为了得到某一个可行解,本质上的思路是数学上的想法和构造的解法
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; }