• hdu1529 差分约束(好题)


    题意:
          超市在每个时间都有需要的人数(24小时)比如 1 0 0 0 0 。。。。也就是说在第0个小时的时候要用一个人,其他的时间都不用人,在给你一些人工作的起始时间,如果雇佣了这个人,那么这个人就会从自己的其实时间工作8个小时后离开,给你需求和可雇佣的员工,问你满足需求超时最少雇佣多少人。

    思路:
          经典的差分约束,之前尝试过很多次都没AC,今天终于AC了,现在我们就来找各种隐含条件。

    设:
    num[i] 表示第i个小时开始的有多少个人。
    r[i] 表示第i个小时最少雇佣多少人。
    s[i] 表示1。。。i小时开始工作的有多少人。 (我们以S为核心建图)

    限制条件:
    第i个小时雇佣并开始工作的人数 >= 0 
    则 s[i] - s[i-1] >= 0
    第i个小时雇佣并开始工作的人数 <= num[i] 
    则 s[i] - s[i-1] <= num[i] 转化成 s[i-1] - s[i] >= -num[i]
    第i个小时雇佣的人数 >= r[i]
    则 s[i] - s[i-8] >= r[i]               (i >= 8 && i <= 24)
       s[24] + s[i] - s[i + 16] >= r[i]    (i <= 7)

    观察最后一个不等式,出现了三个变量,不符合差分约束形式,所以我们就直接二分枚举
    s[24]的值,也就是二分枚举雇佣人数的值,这样就把最后一个转换成
    s[i] - s[i + 16] >= r[i] - mid
    最后别忘了还有一个限制条件就是s[24] - s[0] = mid,=怎么建边呢?我们可以这样
    s[24] - s[0] >= mid并且 s[24] - s[0] <= mid
    第二个转换成 s[0] - s[24] >= -mid;

    这样就可以二分下去了。。。


    #include<stdio.h>
    #include<string.h>
    #include<queue>
    
    #define N_node 30
    #define N_edge 10000
    #define INF 1000000000
    
    using namespace std;
    
    typedef struct
    {
       int to ,cost ,next;
    }STAR;
    
    STAR E[N_edge];
    int list[N_node] ,tot;
    int s_x[N_node];
    int r[30] ,num[1100];
    
    void add(int a ,int b ,int c)
    {
       E[++tot].to = b;
       E[tot].cost = c;
       E[tot].next = list[a];
       list[a] = tot;
    }
    
    bool Spfa(int s ,int n)
    {
       for(int i = 0 ;i <= n ;i ++)
       s_x[i] = -INF;
       int mark[N_node] = {0};
       int in[N_node] = {0};
       s_x[s] = 0;
       mark[s] = in[s] = 1;
       queue<int>q;
       q.push(s);
       while(!q.empty())
       {
          int xin ,tou;
          tou = q.front();
          q.pop();
          mark[tou] = 0;
          for(int k = list[tou] ;k ;k = E[k].next)
          {
             xin = E[k].to;
             if(s_x[xin] < s_x[tou] + E[k].cost)
             {
                s_x[xin] = s_x[tou] + E[k].cost;
                if(!mark[xin])
                {
                   mark[xin] = 1;
                   if(++in[xin] > n) return 0;
                   q.push(xin);
                }
            }
          }
       }
       return 1;
    }
    
    bool ok(int mid)
    {
       memset(list ,0 ,sizeof(list));
       tot = 1;
       for(int i = 1 ;i <= 24 ;i ++)
       {
          add(i - 1 ,i ,0);
          add(i ,i - 1 ,-num[i]);
          if(i >= 8) add(i - 8 ,i ,r[i]);
          else add(i + 16 ,i ,r[i] - mid);
       }
       add(0 ,24 ,mid);
       add(24 ,0 ,-mid);
       return Spfa(0 ,24);
    }
       
    int main ()
    {
       int t ,i ,a ,n;
       scanf("%d" ,&t);
       while(t--)
       {
          for(i = 1 ;i <= 24 ;i ++)
          scanf("%d" ,&r[i]);
          scanf("%d" ,&n);
          memset(num ,0 ,sizeof(num));
          for(i = 1 ;i <= n ;i ++)
          {
             scanf("%d" ,&a);
             num[a+1] ++;
          }
          int low ,mid ,up;
          low = 0 ,up = n;
          int ans = -1;
          while(low <= up)
          {
             mid = (low + up) >> 1;
             if(ok(mid))
             {
                ans = mid;
                up = mid - 1;
             }
             else low = mid + 1;
          }
          if(ans == -1) puts("No Solution");
          else printf("%d
    " ,ans);
       }
       return 0;
    }
       
    
    


  • 相关阅读:
    uiatuomator如何调试
    uiatuomator提示shortMsg=java.lang.RuntimeException
    uiatuomator命令启动apk,与查找多个相同控件
    uiautomator日志文件转换为xml格式文件
    uiautomator做自动化的过程
    uiautomator的坑和AAPT命令方式启动一个应用程序
    ADB无线连接
    用fiddler工具做接口测试
    简单的monkey使用
    疯狂学习java web2(css)
  • 原文地址:https://www.cnblogs.com/csnd/p/12063030.html
Copyright © 2020-2023  润新知