关闭

uvalive 6902 Three Squares - dfs

标签: 二分dfs贪心
317人阅读 评论(0) 收藏 举报
分类:

题目链接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4914

题目意思:用三个相等的正方形去覆盖所有的点,求正方形的最小边长。


解题思路:


首先二分边长,然后找出最小的正方形覆盖所有的点,并从这个正方形的四个顶点开始搜索,如图中假设此时边长为3,首先从左上顶点用边长为3的小正方形去覆盖,标记下所有在此正方形内的点,dfs进入下一层,再找出剩下点的最小正方形覆盖所有点的四个顶点,再继续搜索。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100000+10
#define inf 0x3fffffff

struct Node{
    int x,y;
    Node(){}
}p[maxn];
struct Side{
    int u,d,l,r;
    Side(){}
    Side(int a,int b,int c,int d):u(a),d(b),l(c),r(d){}
};
int n;
bool vis[maxn];

Side findSide(){
    int u=-inf,d=inf,l=inf,r=-inf;
    for(int i=0;i<n;i++){
        if(vis[i]) continue;
        if(p[i].x<l) l = p[i].x;
        if(p[i].x>r) r = p[i].x;
        if(p[i].y<d) d = p[i].y;
        if(p[i].y>u) u = p[i].y;
    }
    return Side(u,d,l,r);
}

bool inside(int x,int y,int i,int m,int k){
    int xx = p[i].x, yy = p[i].y;
   // if(x==0 && y==3 && m==1 && k==1) cout << "!!!" <<xx <<" " <<yy<<endl;
    if(k==1){  // top-left
        if(xx>=x && xx<=x+m && yy>=y-m && yy<=y) return true;
    }else if(k==2){  //top-right
        if(xx>=x-m && xx<=x && yy>=y-m && yy<=y) return true;
    }else if(k==3){  // bottom-left
        if(xx>=x && xx<=x+m && yy>=y && yy<=y+m) return true;
    }else if(k==4){  //bottom-right
        if(xx>=x-m && xx<=x && yy>=y && yy<=y+m) return true;
    }
    return false;
}

bool dfs(int m,int h){
    if(h>3){
        int cnt = 0;
        for(int i=0;i<n;i++) if(vis[i]) cnt++;
        return cnt == n;
    }
    Side temp = findSide();
    int l=temp.l, r = temp.r, u = temp.u, d = temp.d;
    //printf("####h:%d m:%d %d %d %d %d\n",h,m,l,r,u,d);
    //top-left (l,u)
    for(int i=0;i<n;i++){
        if(inside(l,u,i,m,1)){
            vis[i] = true;
            //printf("**%d %d\n",p[i].x,p[i].y);
        }
    }
    if(dfs(m,h+1)) return true;
    else{
        for(int i=0;i<n;i++){
            if(inside(l,u,i,m,1)) vis[i] = false;
        }
    }

    //top-right (r,u)
    for(int i=0;i<n;i++){
        if(inside(r,u,i,m,2)) vis[i] = true;
    }
    if(dfs(m,h+1)) return true;
    else{
        for(int i=0;i<n;i++){
            if(inside(r,u,i,m,2)) vis[i] = false;
        }
    }
    //bottom-left(l,d)
    for(int i=0;i<n;i++){
        if(inside(l,d,i,m,3)) vis[i] = true;
    }
    if(dfs(m,h+1)) return true;
    else{
        for(int i=0;i<n;i++){
            if(inside(l,d,i,m,3)) vis[i] = false;
        }
    }
    //bottom-right(r,d)
    for(int i=0;i<n;i++){
        if(inside(r,d,i,m,4)) vis[i] = true;
    }
    if(dfs(m,h+1)) return true;
    else{
        for(int i=0;i<n;i++){
            if(inside(r,d,i,m,4)) vis[i] = false;
        }
    }
    return false;
}

void solve(){
    int l=0,r=inf,m;
    while(l<r){
        memset(vis,false,sizeof(vis));
        m = (l+r)>>1;
        if(dfs(m,1)) r = m;
        else l = m+1;
    }
    printf("%d\n",r);
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d %d",&p[i].x,&p[i].y);
        }
        solve();
    }
    return 0;
}


0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

UVALive 4670(AC自动机)

题意:有n个串,输出在t串出现次数最多的那个串,如果有多个按照输入顺序输入 题解:模板多,长度短,文本串长。适合多模式串匹配,适用AC自动机,这里使用map映射stirng为...
  • qq_24489717
  • qq_24489717
  • 2016-02-26 18:14
  • 337

UVALive 6837 (最小生成树)

题意是给定一个联通图,求这个图的最小生成树的不可替代边有哪些,并计算这些边的总权值. 先求出任意一棵MST,然后标记树边和非树边,然后枚举非树边,对于非树边的两个点u,v,在MST中如果u->v的路...
  • morejarphone
  • morejarphone
  • 2015-12-07 13:32
  • 275

uvalive 4356 火势控制系统

在平面上有n个目标点,目标是找出一个圆心在(0,0)点处的扇形,至少覆盖其中的k个点,使得该扇形的面积最小 思路先枚举r再枚举角度 #include #include #include ...
  • u014664226
  • u014664226
  • 2015-06-15 21:34
  • 902

Python学习笔记1

摘自Python编程从入门到实践
  • Trisyp
  • Trisyp
  • 2017-04-14 15:42
  • 170

UVALive 7037 (最大密度子图 网络流)

每个数都看成一个节点,每个逆序对之间的节点连边,于是只需要求出这个图的最大密度子图,可以用最小割模型解决. #include #include #include #include #incl...
  • morejarphone
  • morejarphone
  • 2016-03-22 16:15
  • 474

UVALive 4126 (ac自动机做状态类)

题意: 给定最多10个长度不超过10的子串,让构造长度为n(n 分析: 暴力是26^25中可能性,那么怎样精简状态,可以定义d[ i ][ j ][ s ]为当前构造的串长为i且已经到达自动机j...
  • playwfun
  • playwfun
  • 2015-10-09 15:40
  • 329

UVALive 3983(单调队列优化dp)

链接:点击打开链接 题意:有n个垃圾,第i个垃圾坐标为(xi,yi),重量为wi,有一个机器人,要按照编号从小到大的顺序剑气所有的垃圾兵扔进垃圾桶,垃圾桶在源点,每次总重量不能超过C,两点间距离为曼...
  • stay_accept
  • stay_accept
  • 2016-11-20 16:00
  • 239

UVALive - 4882 Parenthesis 表达式处理、字符串处理、栈

题意:给一个有括号小写字母加号组成的字符串,去掉多余的括号后输出。 表表达式处理、字符串处理、栈 用栈,O(n)预处理出每个左括号i 对应的右括号mp[i]的位置, 然后扫一遍mp,对于每个括号判断左...
  • ProLightsfxjh
  • ProLightsfxjh
  • 2017-01-16 19:15
  • 702

UVALive 4728 Squares(旋转卡壳求凸包直径)

给出平面上的n个矩形,求所有顶点对中距离的最大值。显然最大距离的顶点对在凸包上,而求凸包直径,当然用旋转卡壳了。。。 #include #include #include #include #inc...
  • diary_yang
  • diary_yang
  • 2013-08-27 10:55
  • 1189

UVALive 4730 -树状数组+带权并查集

题意:有T组测试数据,每组数据的N表示有N个城市,接下来的N行里每行给出每个城市的坐标(0 (1)"road A B",表示将城市A和城市B通过一条道路连接,如果A和B原来属于不同的城市群,经过这个...
  • viphong
  • viphong
  • 2016-08-18 23:19
  • 165
    个人资料
    • 访问:65120次
    • 积分:1964
    • 等级:
    • 排名:千里之外
    • 原创:137篇
    • 转载:5篇
    • 译文:0篇
    • 评论:21条
    最新评论