pku 1691 Painting A Board 状态压缩dp

DFS解法:http://www.cnblogs.com/E-star/archive/2012/08/11/2633842.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;

}

 

你可能感兴趣的:(paint)