同样是搜索经典题。
优化并不多,只需在当前步数已经大于目前答案时剪枝就可以了。
此题重点在于如何判断第k个矩形能不能选。
设矩形i的左上坐标为i(squ[i].upx,squ[i].upy),右下角坐标为i(squ[i].dox,squ[i].doy)。则判断k号矩形可以涂的条件为:
if(!vis[i]&&(squ[k].upy==squ[i].doy)&&((squ[i].upx>=squ[k].upx&&squ[i].upx<=squ[k].dox)||(squ[i].dox>=squ[k].upx&&squ[i].dox<=squ[k].dox)))
即:如果i号矩形没有涂色且i号矩形为紧靠k上方的矩形,就不可以涂色。
重点来解释一下如何判定i号矩形为紧靠k矩形上方的矩形。
第一,如果i号矩形为紧靠k矩形上方的矩形,那么i号矩形右下角的纵坐标一定等于k号矩形左上角的纵坐标,这个很好理解,对应判断条件中的(squ[k].upy==squ[i].doy)。
第二,如何判断[squ[i].upx,squ[i].dox]和[squ[k].upx,squ[i].dox]有没有交集呢?只需要看是否有一个端点位于线段中即可,读者可以结合下图理解:
下面正常深搜即可。
下面给出参考代码:
#include<iostream> #include<cstdio> #define N 205 using namespace std; struct node { int upx,upy,dox,doy,col; }squ[N]; int n,ans; bool vis[N]; bool check(int k) { for(int i=1;i<=n;i++) { if(!vis[i]&&(squ[k].upy==squ[i].doy)&&((squ[i].upx>=squ[k].upx&&squ[i].upx<=squ[k].dox)||(squ[i].dox>=squ[k].upx&&squ[i].dox<=squ[k].dox)))return 0; } return 1; } void dfs(int step,int node,int col) { if(step>=ans)return; if(node==n)ans=step; for(int i=1;i<=n;i++) { if(!vis[i]&&check(i)) { if(squ[i].col==col) { vis[i]=1; dfs(step,node+1,col); vis[i]=0; } else { vis[i]=1; dfs(step+1,node+1,squ[i].col); vis[i]=0; } } } } int main() { cin>>n; ans=n; for(int i=1;i<=n;i++) { cin>>squ[i].upy>>squ[i].upx>>squ[i].doy>>squ[i].dox>>squ[i].col; } dfs(0,0,-1); cout<<ans<<endl; }