您的位置:首页 > 大数据 > 人工智能

pku 1691 Painting A Board 状态压缩dp

2012-08-11 21:07 288 查看
DFS解法:/article/7104932.html

http://poj.org/problem?id=1691

题意:

给定一个大矩形,然后给出n个需要染色的小矩形的左上角的坐标,右下角的坐标以及该矩形要染得颜色,每个颜色对应的一把刷子。问将这些小矩形染完规定的颜色之后需要最少的刷子数。

要求:只当该小矩形的上边的矩形都染完色之后,该矩形才能染色,如果同一个刷子被使用多次也要计算进来;

View Code

#include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 17
using namespace std;

const int inf = 99999999;

struct node
{
int lx,ly;
int rx,ry;
int col;
}p[maxn];

int dp[1<<maxn][maxn];
int mp[maxn],n,state;
void init()
{
memset(mp,0,sizeof(mp));
int i,j;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
if (i != j && p[i].ry == p[j].ly && !(p[j].rx < p[i].lx || p[j].lx > p[i].rx))
{
mp[j] |= (1<<i);//记录j上边所有的矩形
}
}
}
//初始化
for (i = 0; i < state; ++i)
{
for (j = 0; j < n; ++j)
{
dp[i][j] = inf;
}
}
//初始化上边矩形个数为0的
for (i = 0; i < n; ++i)
{
if (mp[i] == 0) dp[1<<i][i] = 1;
}
}
void DP()
{
int i,j,k;

for (i = 0; i < state; ++i)
{
for (j = 0; j < n; ++j)
{
if ((i&(1<<j)) == 0 && (i&(mp[j])) == mp[j])//如果i状态里面还不存在j矩形并且j上边的矩形在i这个状态里面都染过色了
{
for (k = 0; k < n; ++k)
{
if (i&(1<<k))//i这个状态里面存在k我们才能有他推加入j的情况
{
if (p[k].col == p[j].col)
dp[i + (1<<j)][j] = min(dp[i + (1<<j)][j],dp[i][k]);
else
dp[i + (1<<j)][j] = min(dp[i + (1<<j)][j],dp[i][k] + 1);
}
}
}
}
}

int Min = inf;
for (i = 0; i < n; ++i)
{
//printf(">>%d\n",dp[state - 1][i]);
if (Min > dp[state - 1][i]) Min = dp[state - 1][i];
}
printf("%d\n",Min);
}
int main()
{
//freopen("d.txt","r",stdin);
int t,i;
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
for (i = 0; i < n; ++i)
scanf("%d%d%d%d%d",&p[i].ly,&p[i].lx,&p[i].ry,&p[i].rx,&p[i].col);
state = (1<<n);//记录所有状态
init();
DP();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: