88888888y

导航

 

题目:https://www.luogu.com.cn/problem/P1283

题目简述:用蘸有各种颜色的刷子涂被划分出各个区块的地板,保证每个区块涂色之前,在它上面的区块早已经涂色完毕,求抬起刷子的最小值

思路:n<=16,来一个剪枝就足够了

时间复杂度:O(能过)

 

#include<bits/stdc++.h>
using namespace std;
int n,i,ans,a1[17],b1[17],a2[17],b2[17],c[17],v[17]={0};
//ans是拿刷子的数量
//b是纵,a是横,1是左上,2是右下
//c表示该区块需要的颜色,v表示该区块是否被涂色 
inline bool f(int k){//检查 
	for(int i=1;i<=n;++i){//一个区块一个区块的来 
		if(b2[i]==b1[k]&&((a1[i]>=a1[k]&&a1[i]<=a2[k])||(a2[i]>=a1[k]&&a2[i]<=a2[k]))&&!v[i]){
		//首先,如果循环中的区块的右下角的点的纵坐标 
		//与当前正在检查的区块的左上角的点的坐标相等 
		//则可以知道,他们的上下边界是没有空隙的 
		//如果还满足前正在检查的区块的左边界 
		//在循环中的区块的左右边界之间
		//或者还满足正在检查的区块的右边界 
		//在循环中的区块的左右边界之间 
		//那么就证明,循环中的区块
		//就是紧靠正在检查的区块上方的区块 
		//这种时候告诉的,上面的这个区块没有涂色 
		//那“正在检查的区块”也就无法涂色了 
			return 0;//再见 
		} 
	}
	//上面每个区块都没让它再见
	//那这个区块就是可以涂的了 
	return 1;//返回“真,即“它可以涂色” 
}
inline void dfs(int t,int s,int o){
	if(t>=ans){//当前次数已经大于当前已知的最小值 
		return;//再见 
	}
	if(s==n){//搜完了,也没有再见 
		ans=t;//更新最小值 
		return;//手动再见 
	}
	for(int i=1;i<=n;i++){//一个个区块的来 
		if(!v[i]&&f(i)){//没上过色并且可以上色 
			v[i]=1;//标记“已涂色” 
			if(c[i]==o){//如果还是原来的那种颜色 
				dfs(t,s+1,o);//不用换刷子 
			}
			else{//如果不是 
				dfs(t+1,s+1,c[i]);//换刷子 
			}
			v[i]=0;//回溯 
		}
	}
}
int main(){
	scanf("%d",&n);//常规输入 
	ans=n;//就算是每个区块换一次刷子
	//换n次也就够了,所以ans的初始值定为n就足矣应对 
	for(i=1;i<=n;++i){//常规输入 
		scanf("%d%d%d%d",&b1[i],&a1[i],&b2[i],&a2[i]);
		scanf("%d",&c[i]);
	}
	dfs(0,0,0);//从0搜起 
	printf("%d",ans);
	return 0;
}

 

题目总结重难点
在于
这个
格子
是否
涂色
的检查
剪枝并没有考到太多
这提醒了我们,多注意数据范围,免得WA或者是做无用功
posted on 2022-03-25 16:49  88888888y  阅读(172)  评论(0)    收藏  举报