【网络流24题】 No.10 餐巾计划问题 (线性规划网络优化 最小费用最大流)

【题意】

  一个餐厅在相继的 N 天里, 每天需用的餐巾数不尽相同。 假设第 i 天需要 ri 块餐巾(i=1,2,…, N)。 餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f分;或者送到慢洗部, 洗一块需 n 天(n>m),其费用为 s<f分。每天结束时, 餐厅必须决定将多少块脏的餐巾送到快洗部, 多少块餐巾送到慢洗部, 以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和, 要满足当天的需求量。试设计一个算法为餐厅合理地安排好 N 天中餐巾使用计划,使总的花费最小。

输入文件示例
input.txt
3 10 2 3 3 2
5
6
7

输出文件示例
output.txt
145

 

 

【分析】

  我建的图真是又复杂又有问题,二分图建法就很漂亮。(好吧只是类似二分图,就是分成了两个部分。。[%¥%&¥这是拆点吧。。)

把每天要用的和用完的分离开处理,建模后就是二分图。二分图X集合中顶点Xi表示第i天用完的餐巾,其数量为ri,所以从S向Xi连接容量为ri的边作为限制。Y集合中每个点Yi则是第i天需要的餐巾,数量为ri,与T连接的边容量作为限制。每天用完的餐巾可以选择留到下一天(Xi->Xi+1),不需要花费,送到快洗部(Xi->Yi+m),费用为f,送到慢洗部(Xi->Yi+n),费用为s。每天需要的餐巾除了刚刚洗好的餐巾,还可能是新购买的(S->Yi),费用为p。

转自:http://hzwer.com/1894.html (ORZ HZW。。。)

 

 

  好像可以三分??我不会。。。让我找找三分题解。。。

  好吧看完了,不懂。。直接放链接了:

  http://blog.csdn.net/cgh_Andy/article/details/52449269?locationNum=2&fps=1

  %%%%% 这题是10^5 网络流过不了TAT 三分smg。。。 [他竟然单峰smg!!!

 

  关于线性规划网络优化,一般是 有 : 决策变量 优化目标 约束 对应网络流的话 决策变量就是优化目标就是本题的费用 约束就是满流限制

  好像是这样的吧 b.a..

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 using namespace std;
  9 #define Maxn 2010
 10 #define INF 0xfffffff
 11 
 12 struct node
 13 {
 14     int x,y,f,o,c,next;
 15 }t[Maxn*1010];int len;
 16 int first[Maxn];
 17 
 18 int mymin(int x,int y) {return x<y?x:y;}
 19 int mymax(int x,int y) {return x>y?x:y;}
 20 
 21 void ins(int x,int y,int f,int c)
 22 {
 23     t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;
 24     t[len].next=first[x];first[x]=len;t[len].o=len+1;
 25     t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c;
 26     t[len].next=first[y];first[y]=len;t[len].o=len-1;
 27 }
 28 
 29 int st,ed;
 30 queue<int > q;
 31 int dis[Maxn],pre[Maxn],flow[Maxn];
 32 bool inq[Maxn];
 33 bool bfs()
 34 {
 35     while(!q.empty()) q.pop();
 36     memset(dis,63,sizeof(dis));
 37     memset(inq,0,sizeof(inq));
 38     q.push(st);dis[st]=0;flow[st]=INF;inq[st]=1;
 39     while(!q.empty())
 40     {
 41         int x=q.front();
 42         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 43         {
 44             int y=t[i].y;
 45             if(dis[y]>dis[x]+t[i].c)
 46             {
 47                 dis[y]=dis[x]+t[i].c;
 48                 pre[y]=i;
 49                 flow[y]=mymin(flow[x],t[i].f);
 50                 if(!inq[y])
 51                 {
 52                     inq[y]=1;
 53                     q.push(y);
 54                 }
 55             }
 56         }
 57         inq[x]=0;q.pop();
 58     }
 59     if(dis[ed]>=INF-10000000) return 0;
 60     return 1;
 61 }
 62 
 63 void output()
 64 {
 65     for(int i=1;i<=len;i+=2)
 66      printf("%d->%d %d %d\n",t[i].x,t[i].y,t[i].f,t[i].c);
 67     printf("\n");
 68 }
 69 
 70 void max_flow()
 71 {
 72     int ans=0,sum=0;
 73     while(bfs())
 74     {
 75         sum+=dis[ed]*flow[ed];
 76         ans+=flow[ed];
 77         int now=ed;
 78         while(now!=st)
 79         {
 80             t[pre[now]].f-=flow[ed];
 81             t[t[pre[now]].o].f+=flow[ed];
 82             now=t[pre[now]].x;
 83         }
 84     }
 85     printf("%d\n",sum);
 86 }
 87 
 88 int nd[Maxn];
 89 int main()
 90 {
 91     int n,p,t1,w1,t2,w2;
 92     scanf("%d%d%d%d%d%d",&n,&p,&t1,&w1,&t2,&w2);
 93     for(int i=1;i<=n;i++)
 94     {
 95         scanf("%d",&nd[i]);
 96     }
 97     len=0;
 98     memset(first,0,sizeof(first));
 99     st=2*n+1;ed=st+1;
100     for(int i=1;i<=n;i++) ins(st,i+n,INF,p);
101     for(int i=1;i<n;i++) ins(i,i+1,INF,0);
102     for(int i=1;i<=n-t1;i++) ins(i,i+t1+n,INF,w1);
103     for(int i=1;i<=n-t2;i++) ins(i,i+t2+n,INF,w2);
104     for(int i=1;i<=n;i++) ins(st,i,nd[i],0),ins(i+n,ed,nd[i],0);
105     max_flow();
106     return 0;
107 }
View Code

 

 

2016-11-04 16:36:11

posted @ 2016-11-04 16:31  konjak魔芋  阅读(413)  评论(0编辑  收藏  举报