zoukankan      html  css  js  c++  java
  • 【NOIP2002提高组T4】矩形覆盖-DFS剪枝

    (本人本题完成于2016-7-21)

    题目大意:用K(不超过4)个矩形覆盖平面上的N(不超过50)个点,求这些矩形面积之和的最小值。

    做法:记录每一个矩形的左下角和右上角坐标,左下角坐标初始化为(inf,inf),右上角坐标初始化为(-inf,-inf)。然后DFS,枚举当前的点在哪一个矩形中,如果当前的点不在枚举到的矩形中,则相应的将矩形扩大到正好覆盖这个点,如果此时矩形之间没有相互覆盖并且矩形的总面积没有超过当前已得的最优解,则继续拓展。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define inf 99999999
    using namespace std;
    int n,k,ans=inf;
    struct dot
    {
      int x,y;
    }d[51];
    struct sqr
    {
      dot l,r;
    }rec[5];
    
    bool conf(int i,int j)
    {
      if (rec[i].l.x==inf||rec[i].l.y==inf||rec[i].r.x==-inf||rec[i].r.y==-inf)
        return 0;
      if (rec[j].l.x==inf||rec[j].l.y==inf||rec[j].r.x==-inf||rec[j].r.y==-inf)
        return 0;
      if (rec[i].l.x>rec[j].r.x||rec[i].l.y>rec[j].r.y) return 0;
      if (rec[j].l.x>rec[i].r.x||rec[j].l.y>rec[i].r.y) return 0;
      return 1;
    } //判断矩形i,j是否相互覆盖
    
    bool can()
    {
      for(int i=1;i<=k;i++)
        for(int j=i+1;j<=k;j++)
          if (conf(i,j)) return 0;
      return 1;
    } //判断矩形间是否相互覆盖
    
    int getS()
    {
      int S=0;
      for(int i=1;i<=k;i++)
        if (rec[i].l.x!=inf) //如果这个矩形还在初始状态,不计算其面积(因为这表示还没有在这个矩形中加入点)
          S+=(rec[i].r.x-rec[i].l.x)*(rec[i].r.y-rec[i].l.y);
      return S;
    } //获取当前矩形的总面积
    
    void dfs(int used)
    {
      if (used==n) //已经加入了n个点,结束搜索
      {
        int S=getS();
        if (S<ans) ans=S;
        return;
      }
      for(int i=1;i<=k;i++)
      {
        sqr temp=rec[i];
        if (rec[i].l.x>d[used+1].x) rec[i].l.x=d[used+1].x;
        if (rec[i].l.y>d[used+1].y) rec[i].l.y=d[used+1].y;
    
        if (rec[i].r.x<d[used+1].x) rec[i].r.x=d[used+1].x;
        if (rec[i].r.y<d[used+1].y) rec[i].r.y=d[used+1].y;
        if (can()&&getS()<ans) dfs(used+1); //剪枝
    rec[i]=temp;
      }
    }
    int main()
    {
      scanf("%d %d",&n,&k);
      for(int i=1;i<=n;i++)
        scanf("%d %d",&d[i].x,&d[i].y);
      for(int i=1;i<=k;i++)
      {
        rec[i].l.x=rec[i].l.y=inf;
        rec[i].r.x=rec[i].r.y=-inf;
      }
      dfs(0); //DFS
      printf("%d",ans);
      return 0;
    }

  • 相关阅读:
    块设备驱动框架分析(一)
    LIN总线协议
    LCD驱动分析(三)时序分析
    str_shuffle — 随机打乱一个字符串
    str_replace — 子字符串替换
    str_repeat — 重复一个字符串
    str_pad — 使用另一个字符串填充字符串为指定长度
    str_getcsv — 解析 CSV 字符串为一个数组
    ltrim — 删除字符串开头的空白字符(或其他字符)
    lcfirst — 使一个字符串的第一个字符小写
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9794014.html
Copyright © 2011-2022 走看看