• The Glorious Karlutka River =)


    sgu438:http://acm.sgu.ru/problem.php?contest=0&problem=438

    题意:有一条东西向流淌的河,宽为 W,河中有 N 块石头,每块石头的坐标(Xi, Yi)和最大承受人数 Ci 已知。现在有 M 个游客在河的南岸,他们想穿越这条河流,但是每个人每次最远只能跳 D 米,每跳一次耗时 1 秒。问他们能否全部穿越这条河流,如果能,最少需要多长时间。 <= N <= 50, 0 < M <= 50, 0 <= D <= 1000, 0 < W(0<= 1000, 0 < Xi < 1000, 0 < Yi < W, 0 <= Ci <= 1000)。刚看完这题,想当然的认为它是一道最小费用流问题。但是当WA之后我才明白,这题并不是去求一个给定网络的最大流,而是计算这个网络随着时间推移每次能够留出多少流量。我们通过枚举时间的方式来决定在什么时刻能够把所有的人全部送到对岸。注意人是可以从河这岸的任意x坐标出发的。

    题解:这是一道费用流。具体的看代码吧。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<cmath>
      7 #define inf 100000000
      8 using namespace std;
      9 const int E=10000;
     10 const int N=302;
     11 struct Node{
     12    int v, cap, cost, next;    //  re记录逆边的下标。
     13 }edge[E];
     14 int n, m;
     15 int  ans;
     16 int k, head[N];
     17 int que[N], pre[N], dis[N];
     18 bool vis[N];
     19 void init(){//初始化
     20    k=ans=0;
     21    memset(head,-1,sizeof(head));
     22 }
     23 void addEdge(int u, int v, int ca, int co){
     24     edge[k].v = v;
     25     edge[k].cap = ca;
     26     edge[k].cost = co;
     27     edge[k].next = head[u];
     28     head[u] = k ++;
     29     edge[k].v = u;
     30     edge[k].cap = 0;
     31     edge[k].cost = -co;
     32     edge[k].next = head[v];
     33     head[v] = k ++;
     34 }
     35 bool spfa(){                  //  源点为0,汇点为n。
     36     int i;
     37     for(i = 0; i <=2*m+1;i++){
     38         dis[i] = inf;
     39         vis[i] = false;
     40     }
     41     queue<int>Q;
     42     Q.push(0);
     43     dis[0]=0;
     44     vis[0] = true;
     45     while(!Q.empty()){       //  这里最好用队列,有广搜的意思,堆栈像深搜。
     46         int u = Q.front();
     47         Q.pop();
     48         vis[u]=0;
     49         for(i = head[u]; i != -1; i = edge[i].next){
     50             int v = edge[i].v;
     51             if(edge[i].cap && dis[v] > dis[u] + edge[i].cost){
     52                 dis[v] = dis[u] + edge[i].cost;
     53                 pre[v] = i;
     54                 if(!vis[v]){
     55                     vis[v] = true;
     56                    Q.push(v);
     57                 }
     58             }
     59         }
     60         vis[u] = false;
     61     }
     62     if(dis[2*m+1] == inf) return false;
     63     return true;
     64 }
     65 int  end(){
     66     int u, p, sum = inf;
     67     for(u = 2*m+1; u != 0; u = edge[p^1].v){//0是超级源点
     68         p = pre[u];
     69         sum = min(sum, edge[p].cap);
     70     }
     71     for(u = 2*m+1; u != 0; u = edge[p^1].v){
     72         p = pre[u];
     73         edge[p].cap -= sum;
     74         edge[p^1].cap += sum;
     75     }
     76     return sum;
     77 }
     78 double d,w;
     79 struct  Point{
     80    double x;
     81    double y;
     82    int val;
     83 }num[60];
     84 int main(){
     85    while(~scanf("%d%d%lf%lf",&m,&n,&d,&w)){
     86         init();//初始化
     87        for(int i=1;i<=m;i++){
     88         scanf("%lf%lf%d",&num[i].x,&num[i].y,&num[i].val);
     89        }
     90        for(int i=1;i<=m;i++){
     91           if(abs(num[i].y)<=d){
     92               addEdge(0,i,n,1);
     93           }
     94        }
     95        for(int i=1;i<=m;i++){
     96           for(int j=1;j<=m;j++){
     97              if(i==j)continue;
     98              double diss=sqrt((num[i].x-num[j].x)*(num[i].x-num[j].x)+(num[i].y-num[j].y)*(num[i].y-num[j].y));
     99              if(diss<=d){
    100                 addEdge(i+m,j,inf,1);
    101              }
    102           }
    103           if(abs(num[i].y-w)<=d){
    104             addEdge(i+m,2*m+1,inf,1);
    105           }
    106           addEdge(i,i+m,num[i].val,0);
    107        }
    108        if(w<=d)addEdge(0,2*m+1,inf,1);
    109        int  s=n,now=0,sum=0;
    110        ans=inf;
    111        while(spfa()){
    112           int y=end();
    113            s-=(dis[2*m+1]-now)*sum+y;
    114            if(s<0)s=0;
    115            sum+=y;now=dis[2*m+1];
    116            int temp=now+(int)ceil(s*1.0/sum);
    117            if(temp<ans)ans=temp;
    118        }
    119        if(ans==inf)printf("IMPOSSIBLE
    ");
    120        else
    121        printf("%d
    ",ans);
    122    }
    123 }
    View Code
  • 相关阅读:
    使用反射调用某个类的成员方法
    java反射机制
    SVProgressHUD
    __objc__
    loadView
    v2ex 下拉刷新 SCRootViewController
    stuck with
    v2ex 下拉刷新模块
    转载
    vue-cli脚手架构建了项目如何去除Eslint验证(语法格式验证)
  • 原文地址:https://www.cnblogs.com/chujian123/p/3948582.html
Copyright © 2020-2023  润新知