POJ 2836 Rectangular Covering

本文探讨了如何使用一组边平行于坐标轴的矩形覆盖平面上的n个点,并确保每个点至少被一个矩形覆盖的问题。目标是最小化所有矩形的总面积。文章提供了一种基于动态规划的方法来解决此问题。
Rectangular Covering
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 2813 Accepted: 800

Description

n points are given on the Cartesian plane. Now you have to use some rectangles whose sides are parallel to the axes to cover them. Every point must be covered. And a point can be covered by several rectangles. Each rectangle should cover at least two points including those that fall on its border. Rectangles should have integral dimensions. Degenerate cases (rectangles with zero area) are not allowed. How will you choose the rectangles so as to minimize the total area of them?

Input

The input consists of several test cases. Each test cases begins with a line containing a single integer n (2 ≤ n ≤ 15). Each of the next n lines contains two integers xy (−1,000 ≤ xy ≤ 1,000) giving the coordinates of a point. It is assumed that no two points are the same as each other. A single zero follows the last test case.

Output

Output the minimum total area of rectangles on a separate line for each test case.

Sample Input

2
0 1
1 0
0

Sample Output

1

Hint

The total area is calculated by adding up the areas of rectangles used.

#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
int x[17],y[17];
int dp[1<<16];
struct node
{
    int area,S;
}c[404];
int main()
{
    int n;
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;i++)
            scanf("%d%d",&x[i],&y[i]);
        int tol=0;
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)//枚举每一种组合的两个端点
            {
                c[tol].area=max(1,abs(x[i]-x[j]))*max(1,abs(y[i]-y[j]));
                c[tol].S=(1<<i)|(1<<j);
                for(int k=0;k<n;k++)//在里面的点
                {
                    if((x[k]-x[i])*(x[k]-x[j])<=0&&(y[k]-y[i])*(y[k]-y[j])<=0)
                        c[tol].S=c[tol].S|(1<<k);
                }
                tol++;
            }
        }
        for(int i=0;i<1<<n;i++)dp[i]=1e9;
        dp[0]=0;
        for(int S=0;S<1<<n;S++)//dp
        {
            for(int i=0;i<tol;i++)
            {
                int p=S|c[i].S;
                dp[p]=min(dp[p],dp[S]+c[i].area);
            }
        }
        printf("%d\n",dp[(1<<n)-1]);
    }
    return 0;
}

C语言:在 LIT 综教楼后有一个深坑,关于这个坑的来历,有很多种不同的说法。其中一种说法是,在很多年以前,这个坑就已经在那里了。这种说法也被大多数人认可,这是因为该坑有一种特别的结构,想要人工建造是有相当困难的。   从横截面图来看,坑底成阶梯状,由从左至右的 1..N 个的平面构成(其中 1 ≤ N ≤ 100,000),如图:    *            * :    *            * :    *            * 8    *    **      * 7    *    **      * 6    *    **      * 5    *    ********* 4 <- 高度    *    ********* 3    ************** 2    ************** 1 平面 |  1  |2|   3    | 每个平面 i 可以用两个数字来描述,即它的宽度 Wi 和高度 Hi,其中 1 ≤ Wi ≤ 1,000、1 ≤ Hi ≤ 1,000,000,而这个坑最特别的地方在于坑底每个平面的高度都是不同的。每到夏天,雨水会把坑填满,而在其它的季节,则需要通过人工灌水的方式把坑填满。灌水点设在坑底位置最低的那个平面,每分钟灌水量为一个单位(即高度和宽度均为 1)。随着水位的增长,水自然会向其它平面扩散,当水将某平面覆盖且水高达到一个单位时,就认为该平面被水覆盖了。   请你计算每个平面被水覆盖的时间。输入的第一行是一个整数 N,表示平面的数量。从第二行开始的 N 行上分别有两个整数,分别表示平面的宽度和高度。 输出   输出每个平面被水覆盖的时间。 测试输入 期待的输出 时间限制 内存限制 额外进程 测试用例 1 以文本方式显示 3↵ 4 2↵ 2 7↵ 6 4↵ 以文本方式显示 4↵ 50↵ 26↵ 1秒 1024KB 0 测试用例 12 以文本方式显示 3↵ 4 2↵ 6 4↵ 2 7↵ 以文本方式显示 4↵ 18↵ 50↵ 1秒 1024KB 0
最新发布
10-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值