题目:平板涂色
思路:裸的状压dp。
代码:
#include<bits/stdc++.h>
using namespace std;
struct sqr{
int x1,y1,x2,y2,c;
sqr(){}
};
#define maxn 16
#define maxc 20
#define read(x) scanf("%d",&x)
int n;
sqr a[maxn+5];
vector<int> g[maxn+5];
int d[maxn+5];
int f[(1<<maxn)+5][maxc+5];
int main() {
read(n);
for(int i=1;i<=n;i++) {
read(a[i].y1),read(a[i].x1),read(a[i].y2),read(a[i].x2),read(a[i].c);
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(a[i].y2==a[j].y1&&((a[i].x2>=a[j].x1&&a[i].x2<=a[j].x2)||(a[i].x1<=a[j].x2&&a[i].x1>=a[j].x1))) {
g[j].push_back(1<<i-1),d[i]++;
}
}
}
int S=(1<<n);
for(int i=1;i<S;i++) for(int j=0;j<=20;j++) f[i][j]=(1<<30);
for(int i=1;i<=n;i++) {
if(a[i].y1==0) f[1<<i-1][a[i].c]=1;
}
for(int i=0;i<=20;i++) f[0][i]=1;
for(int i=1;i<S;i++) {
int x=i;
for(int j=1;j<=n;j++) {
if(x&(1<<j-1)) {
for(int k=0;k<g[j].size();k++) {
if(!(x&g[j][k])) goto End;
}
for(int k=0;k<=20;k++) f[x][a[j].c]=min(f[x][a[j].c],f[x^(1<<j-1)][k]+(k!=a[j].c));
End:;
}
}
}
int ans=(1<<30);
for(int i=0;i<=20;i++) ans=min(ans,f[S-1][i]);
printf("%d",ans);
return 0;
}