这个就是15个矩形,按照涂了没涂,2^15次方个状态
然后就可以dp了
dp[i][k]表示i状态,刷子颜色为k的最优解
其实当时2了,应该k表示最后涂的方格比较好,状态会少一些
预处理出每个方格的前驱方格,然后状态转移的时候只要判断该格子的前驱是否已经涂过即可进行转移。
具体实现看代码
#include
#include
#include
using namespace std;
int turn[21];
char dp[40000][20],text[400000][20];
int n,m;
struct
{
int
x1,y1,x2,y2,cor;
}d[21];
struct
{
int tmp;
char k;
}que[1000001];
int spfa()
{
int front=1,end=1;
memset(dp,111,sizeof(dp));
memset(text,0,sizeof(text));
que[front].tmp=0;
que[front].k=0;
dp[0][0]=0;
while(front<=end)
{
int tmp=que[front].tmp;
int k=que[front++].k;
text[tmp][k]=0;
for(int i=1;i<=n;i++)
{
if((turn[i]&tmp)==turn[i])
if(dp[tmp|(1<<i-1)][d[i].cor]>dp[tmp][k]+(d[i].cor!=k))
{
dp[tmp|(1<<i-1)][d[i].cor]=dp[tmp][k]+(d[i].cor!=k);
if(!text[tmp|(1<<i-1)][d[i].cor])
{
text[tmp|(1<<i-1)][d[i].cor]=1;
que[++end].tmp=tmp|(1<<i-1);
que[end].k=d[i].cor;
}
}
}
}
}
int main()
{
int tcase;
scanf("%d",&tcase);
while(tcase--)
{
memset(turn,0,sizeof(turn));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int
x1,y1,x2,y2,tmp;
scanf("%d
%d %d %d
%d",&d[i].y1,&d[i].x1,&d[i].y2,&d[i].x2,&d[i].cor);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(d[i].y2==d[j].y1)
if(d[j].x1<=d[i].x2)
if(d[j].x2>=d[i].x1)
{
//
printf("%d %d\n",i,j);
turn[j]=(turn[j]|(1<<(i-1)));
}
}
spfa();
int ans=100;
int
tmp=(1<<n)-1;
for(int i=1;i<=20;i++)
if(ans>dp[tmp][i])
ans=dp[tmp][i];
printf("%d\n",ans);
//
for(int i=1;i<=tmp;i++)
//
for(int j=1;j<=2;j++)
//
printf("%d %d %d\n",i,j,dp[i][j]);
}
return 0;
}