放牧代码和思想
专注自然语言处理、机器学习算法
    愛しさ 優しさ すべて投げ出してもいい

POJ 2836 Rectangular Covering 题解 《挑战程序设计竞赛》

目录

POJ 2836 Rectangular Covering

铺地板:坐标平面上有n各点,用任意大小(非零)的地板砖覆盖它们,求最省的地板砖总面积。

3.4熟练掌握动态规划

状态压缩DP

先预处理数据,将n个点两两组合形成n * (n-1) / 2个矩形,计算每个矩形的面积和内部点个数。

接着利用预处理数据来枚举,定义

dp[S] := 矩形集为S时的最省面积

先假设平面上没有矩形,那么dp[0]=0,接着一个一个地往平面上加矩形,递推关系是:

dp[新矩形集合] = min(dp[新矩形集合], dp[旧矩形集合] + 新矩形的面积);

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string.h>

#define MAX_N 16
int x[MAX_N], y[MAX_N], dp[1 << MAX_N]; // dp[S] := 点集为S时的最省面积
using namespace std;

struct Rect
{
    int coverd; // 内含点集
    int area;   // 面积

    Rect(const int& coverd, const int& area) : coverd(coverd), area(area)
    {}

    void add(int i)
    {
        coverd |= 1 << i;
    }
};

/**
* 点k是否在点i和点j围成的矩形中
*/
bool is_in(int i, int j, int k)
{
    return ((x[i] - x[k]) * (x[j] - x[k]) <= 0) && ((y[i] - y[k]) * (y[j] - y[k]) <= 0);
}


int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int n;
    while(cin >> n && n)
    {
        for (int i = 0; i < n; ++i)
        {
            cin >> x[i] >> y[i];
        }
        vector<Rect> rarray;
        for (int i = 0; i < n; ++i)
        {
            for (int j = i + 1; j < n; ++j)
            {
                Rect r((1 << i) | (1 << j), max(1, (int const &) abs(x[i] - x[j])) * max(1, (int const &) abs(y[i] - y[j])));
                for (int k = 0; k < n; ++k)
                {
                    if(is_in(i, j, k))
                    {
                        r.add(k);
                    }
                }
                rarray.push_back(r);
            }
        }
        memset(dp, 0x3f, sizeof(dp));
        dp[0] = 0;  // 包含0个点的矩形的面积是0
        for (vector<Rect>::iterator it = rarray.begin(); it != rarray.end(); ++it)
        {
            for (int s = 0; s < 1 << n; ++s)
            {
                int ns = s | it->coverd;
                if (dp[s] != 0x3f3f3f3f && ns != s)
                {
                    dp[ns] = min(dp[ns], dp[s] + it->area);
                }
            }
        }
        cout << dp[(1 << n) - 1] << endl;
    }
#ifndef ONLINE_JUDGE
    fclose(stdin);
#endif
    return 0;
}
13442976 hankcs 2836 Accepted 528K 141MS C++ 1887B 2014-09-15 12:36:45

知识共享许可协议 知识共享署名-非商业性使用-相同方式共享码农场 » POJ 2836 Rectangular Covering 题解 《挑战程序设计竞赛》

评论 欢迎留言

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

我的作品

HanLP自然语言处理包《自然语言处理入门》