poj 2836 rectangle dp(动态规划)

本文探讨如何通过状态DP技术解决涉及多个点和矩形覆盖的问题,详细介绍了点的枚举、状态转移以及特殊情况的处理策略。通过优化算法实现高效求解,展示了在几何问题中的应用与创新。

状态dp

讲15个点描述成2^15个状态

枚举出15*14/2个矩形所能覆盖的点

然后状态转移就是每个矩形往上面贴

这里边比较麻烦的一点就是如果两个点的横左边或者纵坐标相同,这样它本身不会确定一个矩形

所以就要枚举两个宽为1的矩形,这样使得编写麻烦了很多

后边仔细想了想,其实只要出现这种情况的时候认为只有这两个点能被包围就行了,原因自己想想就明白了

 

代码是后边的想法的代码

 

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
int x[20],y[20];
int f[1000],are[1000];
const int inf=9999999;

int swap(int &a,int &b)
{
    if(a>b)
    {
        int tmp=a;
        a=b;
        b=tmp;
    }
    return 0;
}

int que[1000001];
int ans[40000],text[40000];

int main()
{
    while(1)
    {
        int n;
        scanf("%d",&n);
        if(!n) break;
        for(int i=1;i<=n;i++)
        scanf("%d %d",&x[i],&y[i]);
        int time=0;
        memset(are,0,sizeof(are));
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(x[i]!=x[j]&&y[i]!=y[j])
            {
                are[++time]=fabs(x[i]-x[j])*fabs(y[i]-y[j]);
                int tmp1=x[i],tmp2=x[j];
                int txt1=y[i],txt2=y[j];
                swap(tmp1,tmp2);
                swap(txt1,txt2);
                for(int k=1;k<=n;k++)
                {
                    if(x[k]>=tmp1&&x[k]<=tmp2)
                    if(y[k]>=txt1&&y[k]<=txt2)
                    f[time]+=1<<(k-1);
                }
            }
            else
            {
                are[++time]=fabs(x[i]-x[j]);
                are[time]+=fabs(y[i]-y[j]);
                f[time]+=1<<(i-1);
                f[time]+=1<<(j-1);
            }
        }
        int front=1,end=1;
        que[front]=0;
        for(int i=1;i<=1<<n;i++)
        ans[i]=inf;
        ans[0]=0;
        memset(text,0,sizeof(text));
        text[0]=1;
        while(front<=end)
        {
            int tmp=que[front++];
            text[tmp]=0;
            for(int i=1;i<=time;i++)
            if(ans[tmp|f[i]]>ans[tmp]+are[i])
            {
                ans[tmp|f[i]]=ans[tmp]+are[i];
                if(!text[tmp|f[i]])
                {
                    text[tmp|f[i]]=1;
                    que[++end]=tmp|f[i];
                }
            }
        }
        printf("%d\n",ans[(1<<n)-1]);
    }
    return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值