COGS103&tyvj1899 [NOIP2002]矩形覆盖

题目里给的范围是k<=4,但是官方数据并没有k==4的情况,导致一些奇奇怪怪的DP写法也能过。听说标程在k==4的时候有反例,掀桌….. 难怪COGS上k==4的数据答案是错的。

还是好好写个搜索吧:网上写法很多.我是每次沿着一条平行于坐标轴的直线将点集分割成两部分,并枚举k个矩形如何在两边分配。边界为k==1,扫一遍所有点找到最小的矩形。细节看代码吧.

但是这个搜索我也不能保证是对的,因为k==4有可能出现这种崎岖的最优方案:不存在一条平行于坐标轴且不和任何一个矩形相交的直线将4个矩形分成两部分.例如这样的最优方案:

贴个代码吧:递归的时候为了处理“将点集分成两部分”调了一堆memcpy….好在递归层数和点数都不多,不然常数炸天....

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=55;
int x[maxn],y[maxn],seq[maxn];
inline int max(int a,int b){
    return a>b?a:b;
}
inline int min(int a,int b){
    return a<b?a:b;
}
bool cmp1(const int &a,const int &b){
    return x[a]<x[b];
}
bool cmp2(const int &a,const int &b){
    return y[a]<y[b];
}
struct node{
    int x1,y1,x2,y2;
    node(){}
    node(int a,int b,int c,int d){
        x1=a;y1=b;x2=c;y2=d;
    }
}sol[10];int cnt=0;
int work(int l,int r,int seq[]){
    int minx=0x7f7f7f7f,miny=0x7f7f7f7f,maxx=0,maxy=0;
    for(int i=l;i<=r;++i){//printf("seq%d\n",seq[i]);
        minx=min(minx,x[seq[i]]);maxx=max(maxx,x[seq[i]]);
        miny=min(miny,y[seq[i]]);maxy=max(maxy,y[seq[i]]);
    }
    sol[++cnt]=node(minx,miny,maxx,maxy);
    return (maxx-minx)*(maxy-miny);
}
int s[1000][55];int tot=0;
int dfs(int l,int r,int k,int seq[]){//printf("%d\n",k);
    if(k==1){
        int tmp=work(l,r,seq);
        cnt--;
        return tmp;
    }else{
        int ans=0x7f7f7f7f;
        sort(seq+l,seq+r+1,cmp1);
        for(int i=l;i<r;++i){
            for(int j=1;j<k;++j){
                ++tot;
                memcpy(s[tot],seq,sizeof(int)*55);
                ++tot;
                memcpy(s[tot],seq,sizeof(int)*55);
                if(x[seq[i]]!=x[seq[i+1]]){
                    int tmp=dfs(l,i,j,s[tot-1])+dfs(i+1,r,k-j,s[tot]);
                    ans=min(ans,tmp);
                }
                --tot;--tot;
                //printf("---------------\n");
            }
        }//printf("%d\n",ans);
        sort(seq+l,seq+r+1,cmp2);
        for(int i=l;i<r;++i){
            for(int j=1;j<k;++j){
                ++tot;
                memcpy(s[tot],seq,sizeof(int)*55);
                ++tot;
                memcpy(s[tot],seq,sizeof(int)*55);
                if(y[seq[i]]!=y[seq[i+1]]){
                    int tmp=dfs(l,i,j,s[tot-1])+dfs(i+1,r,k-j,s[tot]);
                    ans=min(ans,tmp);
                }
                --tot;--tot;
                //printf("---------------\n");
            }
        }//printf("%d\n",ans);
        return ans;
    }
}
int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i){
        scanf("%d%d",x+i,y+i);
    }
    for(int i=1;i<=n;++i){
        seq[i]=i;
    }
    printf("%d\n",dfs(1,n,k,seq));
    return 0;
}
时间: 2024-10-10 09:45:01

COGS103&tyvj1899 [NOIP2002]矩形覆盖的相关文章

NOIP2002 矩形覆盖

题四 矩形覆盖(存盘名NOIPG4) [问题描述]: 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢.约定:

NOIP2002矩形覆盖[几何DFS]

题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢.约定:覆盖一个点的矩形面积为 0:覆盖平行于坐标轴

BZOJ1185: [HNOI2007]最小矩形覆盖

传送门 旋转卡壳. 首先求凸包没什么好商量的. 然后有一个结论,如果存在一个最小的矩形覆盖,那么凸包里必定存在一条边和矩形的边重合. 自己yy一下就好啦,很容易想明白. 然后枚举每条边,移动另外三条边即可. 注意点积,叉积的结合运用什么的. //BZOJ 1185 //by Cydiater //2017.1.29 #include <iostream> #include <map> #include <ctime> #include <cmath> #in

HDU 5100 Chessboard 用 k &#215; 1 的矩形覆盖 n &#215; n 的正方形棋盘

点击打开链接 Chessboard Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 335    Accepted Submission(s): 168 Problem Description Consider the problem of tiling an n×n chessboard by polyomino pieces tha

1185: [HNOI2007]最小矩形覆盖

1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1426  Solved: 648[Submit][Status][Discuss] Description Input Output Sample Input Sample Output HINT Source 计算几何 vfleaking提供Spj #include<cstdio> #include<cmat

剑指OFFER之矩形覆盖(九度OJ1390)

题目描述: 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入包括一个整数n(1<=n<=70),其中n为偶数. 输出: 对应每个测试案例, 输出用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有的方法数. 样例输入: 4 样例输出: 5 解题思路: 观察题目中的矩形,2*n的,是个长条形.本来脑中想象的是复杂的华容道,但是既然只是简单的长条形,那么

bzoj1185【HNOI2007】最小矩形覆盖

1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1114  Solved: 505 [Submit][Status][Discuss] Description 凸包+旋转卡壳 首先有一个结论:矩形一定有一条边在凸包上,否则我们旋转之后一定会得到一个更小的矩形,脑补一下. 然后枚举凸包上的边,用旋转卡壳维护矩形的另外三条边,同时更新答案即可. #include<ios

[ACM] ZOJ 3209 Treasure Map ( Dancing Links 精确覆盖,矩形覆盖)

Treasure Map Time Limit: 2 Seconds      Memory Limit: 32768 KB Your boss once had got many copies of a treasure map. Unfortunately, all the copies are now broken to many rectangular pieces, and what make it worse, he has lost some of the pieces. Luck

洛谷 P1034 矩形覆盖

P1034 矩形覆盖 题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢.约定:覆盖一个点的矩形面积为