P1283 平板涂色
数据范围很小,直接考虑状压或者暴搜,这里考虑状压。
那就需要考虑我们选了一个集合 ,很自然能够想到把每个矩形是/否涂过色标记为 ,从而衍生为一个集合。
转移的话也很简单,在枚举所有集合 的时候,直接枚举可以使用的颜色,大力模拟出来使用了当前画笔后的集合情况为 ,方程就是:
思路看起来很清晰,但是实际操作起来难度比较大,写到吐。
开始的时候应该先排序,按照左上角的横坐标来排,这样才能保证在从上往下覆盖的时候不会漏掉矩形。
在判断矩形的时候,考虑直接用一个数组标记矩形靠上的那条长上的所有点的覆盖情况,注意,当前矩形靠上的长和另一个矩形靠下的长在同一直线,但是交集为 的时候,题目不认为这属于“覆盖”的范畴,那么这个点就不能被标记了。
当然你也不能用一个二维数组去搞,因为很多点都是重合的,这样会漏掉信息。
同时可以发现,按照我们这样的设法,这题的状态数其实不会很多,跑起来飞快。
#include<bits/stdc++.h>
using namespace std;
const int N =100;
int dp[(1<<16)+20],vis2[N],p[N],c[N],vis[N],vis1[N],cnt,n;
struct node{
int l1,r1,l2,r2;
}a[N];
bool cmp(node a,node b){
return a.l1<b.l1;
}
void col(int x){
for(int i=0;i<n;i++)
if(x>>i&1==1) vis1[i]=true;
}
bool check(int i){
for(int j=0;j<n;j++){
if(i==j||(a[i].l1!=a[j].l2)||vis1[j]==false) continue;
if(a[i].r1<a[j].r2&&a[j].r1<=a[i].r1) for(int k=a[i].r1;k<=a[j].r2;k++) vis2[k]=1;
if(a[i].r2>a[j].r1&&a[j].r2>=a[i].r2) for(int k=a[j].r1;k<=a[i].r2;k++) vis2[k]=1;
}
for(int k=a[i].r1;k<=a[i].r2;k++) if(vis2[k]==0) return false;
return true;
}
void Add(int now,int x){
int lst=now;
for(int i=0;i<n;i++){
if(c[i]!=x||(lst>>i&1==1)) continue;
bool f=true;
memset(vis2,0,sizeof(vis2));
if(a[i].l1!=0) f=check(i);
if(f==true) vis1[i]=true,now|=(1<<i);
}
dp[now]=min(dp[now],dp[lst]+1);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i].l1>>a[i].r1>>a[i].l2>>a[i].r2>>c[i];
if(vis[c[i]]==false) p[cnt++]=c[i],vis[c[i]]=true;
}
sort(a,a+n,cmp);
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
for(int i=0;i<(1<<n);i++){
if(dp[i]==1061109567) continue;
for(int j=0;j<cnt;j++)
memset(vis1,0,sizeof(vis1)),col(i),Add(i,p[j]);
}
cout<<dp[(1<<n)-1]<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现