餐巾计划问题
Posted shatianming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了餐巾计划问题相关的知识,希望对你有一定的参考价值。
这个题非常的好,真的......我半颓半打,打了一下午最后还是去看了题解,,,,
这个题对限制条件的转换非常的好
先贴代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 long long tot=-1,sum=0,h[10005],flow[10005],g[10005],ans=0,dis[10005],ans2=0,inf=999999; 5 bool vis[10005]; 6 struct node{ 7 long long from,to,next,rest,cost; 8 }e[10000005]; 9 10 void add(long long x,long long y,long long z,long long hg){ 11 tot++; 12 e[tot].next=h[x]; 13 h[x]=tot; 14 e[tot].cost=hg; 15 e[tot].from=x; 16 e[tot].to=y; 17 e[tot].rest=z; 18 } 19 20 int bfs(long long s,long long t){ 21 queue<int>q; 22 q.push(s);dis[s]=0;vis[s]=true; 23 while(!q.empty()){ 24 long long u=q.front();q.pop();vis[u]=false; 25 for(int i=h[u];i!=(-1);i=e[i].next){ 26 if(e[i].rest>0&&dis[e[i].to]>dis[u]+e[i].cost){ 27 flow[e[i].to]=min(flow[u],e[i].rest); 28 dis[e[i].to]=dis[u]+e[i].cost; 29 g[e[i].to]=i; 30 if(vis[e[i].to]==false)q.push(e[i].to),vis[e[i].to]=true; 31 } 32 } 33 } 34 } 35 36 int EK(long long s,long long t){ 37 while(1){ 38 memset(flow,0x7f,sizeof(flow)); 39 memset(dis,0x7f,sizeof(dis)); 40 memset(g,-1,sizeof(g)); 41 memset(vis,false,sizeof(vis)); 42 bfs(s,t); 43 if(g[t]!=(-1)){ 44 ans+=flow[t];ans2+=dis[t]*flow[t]; 45 for(int p=t;p!=s;p=e[g[p]].from){ 46 e[g[p]].rest-=flow[t]; 47 e[g[p]^1].rest+=flow[t]; 48 } 49 } 50 else break; 51 } 52 } 53 54 int n,P,m,f,N,S,r; 55 56 int main(){ 57 memset(h,-1,sizeof(h)); 58 cin>>n>>P>>m>>f>>N>>S; 59 for(int i=1;i<=n;i++){ 60 cin>>r; 61 add(0,i,r,0); 62 add(i,0,0,0); 63 add(i+n,2*n+1,r,0); 64 add(2*n+1,i+n,0,0); 65 add(0,i+n,inf,P); 66 add(i+n,0,0,-P); 67 if(i+m<=n)add(i,i+m+n,inf,f),add(i+m+n,i,0,-f); 68 if(i+N<=n)add(i,i+N+n,inf,S),add(i+N+n,i,0,-S); 69 if(i<n)add(i,i+1,inf,0),add(i+1,i,0,0); 70 } 71 EK(0,2*n+1); 72 cout<<ans2<<endl; 73 }
我原本做这个题的时候,本来是这么想的
1.把节点分为用了和没用,俩俩连边
2.对于买,直接现在1号节点买好(因为后面什么时候买可以),就把源点连1号,同理汇点连n号用过的...
3.对于洗,就把用了的连多少天之后.....
4.然后在上面跑费用流就好了....
5.没用的之间俩俩连边....
但是错了.....
分析了一下,错的原因可能是因为求费用流的同时,通过先前节点走到哪里,比从源点直接到那个点的值大得多.....
那我又想了一下,直接处理一下洗衣服的边权不就可以了嘛.....因为对于洗衣服,相当于少付了这么多
但这东西就很怪.....
想不懂为什么wa了.....
可能是因为下面那条边,就是原本买多了的新衣服有路给过去了.......然后又因为求的是最大流.....
诶,那我把买多了的新衣服去掉,只有剩下的旧衣服会怎么样??,,图就不连通了
....
立个flag,谁用我上面的方法做出来我请你吃饭
好吧,向正解低头
嘛,正解用到了一个引理,就是每天一定能得到要求的衣服,只是途径不同,,,,,
那很好办了.
直接建立两种节点,有和没有用过的.....
然后对于用过的可以根据洗衣服的规则到这么多天的没有用过的....
然后买也可以解决,没用过的可以由买回来转移得到,于是可以把没用过与(与用掉的相连的源点粘接,代表经过买的连接)...
我在说什么....
嘛真的不推荐你们看这篇题解,太垃圾了....
反正啦,(绯红华尔兹好好听)
反正从这题得出了几个经验
1,不要边颓边学
2.要大力猜想题目条件,不能被局限在原有知识里
3.显然的东西就要大力去用
4.不要抄模板,多打一下多好
.
.
.
以上是关于餐巾计划问题的主要内容,如果未能解决你的问题,请参考以下文章