• Occupy Cities


    hdu4606:http://acm.hdu.edu.cn/showproblem.php?pid=4606

    题意:在一个二维坐标系中,有n个城市,坐标给出来了,然后有p个士兵要去占领这n个城市,但是路上有m个路障,都是线段,士兵不能越过路障前进。

    每个士兵都有相同容量大小的一个干粮袋,每到一个城市他就能补充满自己的干粮袋。中途走路时走一个单位长度就消耗一个单位的干粮。

    现在问的是这些个干粮袋最小的容量是多少,前提是保证p个士兵能占领完这n个城市,城市被占领顺序也是题目给好的,必须遵守。

    题解:这一题是一道很好的综合题。首先一点,就是求出任意两个城市的最短距离。这个也是我今天学到的知识。我们可以把障碍的端点当做2个点,如果城市i和城市j之间没有障碍的话,那么i,j之间的距离就可以直接算出。如果有障碍的话,就只能绕过障碍的端点来求。怎么求呢?只要把端点当做路径上的点就可以了,然后用floyd过一遍即可。这里,要用到判断两条线段是否相交的。然后可以联想到的是最小点覆盖。但是这里的是最小点覆盖小于p都是满足的。所以接下来可以二分枚举长度,找到最小额满足条件的长度。用到二分以及二分图的最大匹配。因为最小点覆盖==点数--二分图的最大匹配。还有一个就序列,这也是要考虑。这里只哎哟我们建图的时候,让前面的序列指向后面的序列就可以了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<iostream>
      5 #include<cmath>
      6 using namespace std;
      7 const double inf=1000000000.0;
      8 int n,m,p;
      9 int seq[600],cy[600];
     10 double g[600][600];
     11 bool key[600][600],visit[600];
     12 struct point{
     13    double x,y;
     14 }dian[602];
     15 struct Node{
     16     point a;
     17     point b;
     18 }xian[602];
     19 double dis(int a,int b){
     20   return  sqrt((dian[a].x-dian[b].x)*(dian[a].x-dian[b].x)+(dian[a].y-dian[b].y)*(dian[a].y-dian[b].y));
     21 
     22 }
     23 double Cross( point a,  point b,  point  o){
     24     return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
     25 }
     26 bool IsIntersect( Node u, Node v){
     27     return (Cross(v.a, u.b, u.a) * Cross(u.b, v.b, u.a) > 0) &&
     28            (Cross(u.a, v.b, v.a) * Cross(v.b, u.b, v.a) > 0) &&
     29            (max(u.a.x, u.b.x) > min(v.a.x, v.b.x)) &&
     30            (max(v.a.x, v.b.x) > min(u.a.x, u.b.x)) &&
     31            (max(u.a.y, u.b.y) > min(v.a.y, v.b.y)) &&
     32            (max(v.a.y, v.b.y) > min(u.a.y, u.b.y));
     33 }
     34 
     35 bool judge(int a,int b){
     36     for(int i=1;i<=m;i++){
     37         if((a+1-n)/2==i&&(b+1-n)/2==i)continue;
     38         Node temp;temp.a=dian[a];temp.b=dian[b];
     39         if(IsIntersect(temp,xian[i]))
     40             return false;
     41     }
     42   return true;
     43 }
     44 int path(int u){
     45      for(int i=1;i<=n;i++){
     46         if(!visit[i]&&key[u][i]){
     47             visit[i]=1;
     48         if(cy[i]==-1||path(cy[i])){
     49             cy[i]=u;
     50             return 1;
     51         }
     52        }
     53      }
     54    return 0;
     55 }
     56 int maxmatch(){
     57     memset(cy,-1,sizeof(cy));
     58     int res=0;
     59     for(int i=1;i<=n;i++){
     60     memset(visit,0,sizeof(visit));
     61         res+=path(i);
     62     }
     63     return res;
     64 }
     65 bool task(double mid){
     66     memset(key,0,sizeof(key));
     67     for(int i=1;i<=n;i++)
     68        for(int j=1;j<=n;j++){
     69         if(g[i][j]<=mid&&seq[i]<seq[j])
     70             key[i][j]=1;
     71     }
     72     int as=maxmatch();
     73     if(n-as<=p)return true;
     74     else return false;
     75 }
     76 
     77 double solve(){
     78      double l=0,r=inf,ans=0;
     79      while(abs(l-r)>0.0000001){
     80         double mid=(l+r)/2;
     81         if(task(mid)){
     82             ans=mid;
     83             r=mid;
     84         }
     85         else
     86             l=mid;
     87      }
     88      return ans;
     89 }
     90 int temp;
     91 int main(){
     92     int cas;
     93     scanf("%d",&cas);
     94     while(cas--){
     95         scanf("%d%d%d",&n,&m,&p);
     96         memset(g,0,sizeof(g));
     97        for(int i=1;i<=n;i++){
     98           scanf("%lf%lf",&dian[i].x,&dian[i].y);
     99        }
    100        for(int i=1;i<=m;i++){
    101         scanf("%lf %lf",&xian[i].a.x,&xian[i].a.y);
    102          dian[i*2+n-1].x=xian[i].a.x;
    103          dian[i*2+n-1].y=xian[i].a.y;
    104         scanf("%lf %lf",&xian[i].b.x,&xian[i].b.y);
    105          dian[i*2+n].x=xian[i].b.x;
    106          dian[i*2+n].y=xian[i].b.y;
    107        }
    108        memset(seq,0,sizeof(seq));
    109       for(int i=1;i<=n;i++){
    110           scanf("%d",&temp);
    111           seq[temp]=i;
    112       }
    113        for(int i=1;i<=n+2*m;i++){
    114           for(int j=1;j<=n+2*m;j++){
    115               if(j==i)continue;
    116               if(judge(i,j)){
    117                 g[i][j]=dis(i,j);
    118               }
    119               else
    120                 g[i][j]=inf;
    121           }
    122           g[i][i]=inf;
    123        }
    124        for(int k=1;k<=n+2*m;k++)
    125            for(int i=1;i<=n+2*m;i++)
    126               for(int j=1;j<=n+2*m;j++)
    127                  g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
    128           double ans=0;
    129           ans=solve();
    130       printf("%.2f
    ",ans);
    131     }
    132 }
    View Code
  • 相关阅读:
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    OSCP Learning Notes
    Codeforces Round #601 (Div. 2) E2 Send Boxes to Alice (Hard Version)
    Codeforces Round #601 (Div. 2) E1 Send Boxes to Alice (Easy Version)
  • 原文地址:https://www.cnblogs.com/chujian123/p/3915798.html
Copyright © 2020-2023  润新知