程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 習題:codevs 1035 火車停留解題報告,codevs1035

習題:codevs 1035 火車停留解題報告,codevs1035

編輯:C++入門知識

習題:codevs 1035 火車停留解題報告,codevs1035


本蒟蒻又來寫解題報告了。這次的題目是codevs 1035 火車停留。

題目大意就是給m個火車的到達時間、停留時間和車載貨物的價值,車站有n個車道,而火車停留一次車站就會從車載貨物價值中獲得1%的利潤,讓你來求一種安排方法,使得車站收益最大,並輸出收益值。

蒟蒻的思路是這樣的:

一眼看出:最大費用最大流(MCMF)
顯然cost:表示車站收益
然後……
以車站為點建立圖求流?同一個車站可能經過好幾輛火車……,貌似很麻煩……;
那麼以什麼建圖、連邊,還有怎麼連?
貌似有點類似於方格取數2之中的拆點……;
那麼這個就可以……以火車為點,把一個點拆成兩個,然後建立流的關系。
Reach[i]和stay[i]作為建立不同火車是否可以建邊的判斷條件
假設火車i,將其分為點2*i-1和2*i,連一條流量為1,費用為-cost[i]的邊
如果reach[i] + stay[i] < reach[j],在2*i和2*j-1之間連一條流量為1,費用為0的邊。
建立匯點和起點S,T,從S向每個2*i-1連一條流量為1,費用為0的邊。從每個2*i向T連一條流量為1,費用為0的邊。

那麼怎麼限制n個車道呢?其實很簡單,只需要建立超級匯點ST,然後從T向ST連一條流量為n,費用為0的邊。

這樣這個題目就大功告成了,代碼不長,剛98行。建議大家還是去刷一下代碼能力題,因為NOIP2015蒟蒻就被代碼能力題給坑慘了。

廢話不多說,上代碼

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <queue>
 7 using namespace std;
 8 const int INF = 10000000;
 9 const int maxe = 10000;
10 const int maxn = 500;
11 int n,m,reach[maxn],stay[maxn],cost[maxn],vis[maxn<<1],d[maxn<<1],h[maxn<<1],pre[maxn<<1],rid[maxn],cid[maxn],now;
12 double ans;
13 struct edge{
14     int to,cost,cap,next;
15 }tr[maxe];
16 inline void init(){
17     now = 0;
18     memset(h,-1,sizeof(h));
19     memset(tr,0,sizeof(tr));
20     memset(reach,0,sizeof(reach));
21     memset(stay,0,sizeof(stay));
22     memset(cost,0,sizeof(cost));
23 }
24 inline void add(int u,int v,int cap,int cost){
25     tr[now].to = v;tr[now].cap = cap;tr[now].cost = cost;tr[now].next = h[u];
26     h[u] = now++;
27     tr[now].to = u;tr[now].cap = 0;tr[now].cost = -cost;tr[now].next = h[v];
28     h[v] = now++;
29 }
30 bool SPFA(int s,int t,int &flow,int &cost){
31     for(int i = s;i <= t;++i){
32         d[i] = INF;
33     }
34     int minflow = INF;
35     memset(vis,0,sizeof(vis));
36     memset(pre,-1,sizeof(pre));
37     deque<int>q;
38     d[s] = 0;
39     vis[s] = 1;
40     q.push_back(s);
41     while(!q.empty()){
42         int x = q.front();q.pop_front();
43         vis[x] = 0;
44         for(int i = h[x];i != -1;i = tr[i].next){
45             edge e = tr[i];
46             if(d[e.to] > d[x] + e.cost && e.cap){
47                 d[e.to] = d[x] + e.cost;
48                 pre[e.to] = i;
49                 minflow = min(minflow,e.cap);
50                 if(!vis[e.to]){
51                     vis[e.to] = 1;
52                     q.push_back(e.to);
53                 }
54             }
55         }
56     }
57     if(d[t] == INF)return false;
58     flow += minflow;
59     cost += d[t] * minflow;
60     for(int i = t;i != s;i = tr[pre[i]^1].to){
61         tr[pre[i]].cap -= minflow;
62         tr[pre[i]^1].cap += minflow;
63     }
64     return true;
65 }
66 int MCMF(int s,int t){
67     int flow = 0,cost = 0;
68     while(SPFA(s,t,flow,cost));
69     return cost;
70 }
71 int main(){
72     scanf("%d%d",&n,&m);
73     init();
74     for(int i = 1;i <= m;++i){
75         scanf("%d%d%d",&reach[i],&cost[i],&stay[i]);
76         rid[i] = 2*i;cid[i] = 2*i-1;
77         add(cid[i],rid[i],1,-cost[i]);
78     }
79     for(int i = 1;i <= m;++i){
80         for(int j = 1;j <= m;++j){
81             if(j != i)
82                 if(reach[i] + stay[i] < reach[j]){
83                     add(rid[i],cid[j],1,0);
84                 }
85         }
86     }
87     int S = 0,T = 2*m+1,ST = 2*m+2;
88     for(int i = 1;i <= m;++i){
89         add(S,cid[i],1,0);
90     }
91     for(int i = 1;i <= m;++i){
92         add(rid[i],T,1,0);
93     }
94     add(T,ST,n,0);
95     ans = double(MCMF(S,ST))/100;
96     printf("%0.2lf\n",-ans);
97     return 0;
98 }

如果大家認為有用的話,歡迎轉載。如果大家有意見的話,請在下方評論欄中給我留言,或者給我的E-mail [email protected]發郵件留言。謝謝大家。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved