• 【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;
    }

  • 相关阅读:
    大屏展示功能
    单例模式/原型模式
    .net core ioc
    Log4net
    mvc 过滤器
    webservice
    页面传值 作用域
    Map使用方法
    java获取当前时间撮
    linux 下统计文本行数的各种方法(一)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9794015.html
Copyright © 2020-2023  润新知