• 餐巾计划问题


    这个题非常的好,真的......我半颓半打,打了一下午最后还是去看了题解,,,,

    这个题对限制条件的转换非常的好

    先贴代码

     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.不要抄模板,多打一下多好

    .

    .

    .

  • 相关阅读:
    在ModelSim中添加Xilinx仿真库
    关于DDR3非常棒的文章
    Modelsim编译Xilinx器件库的另一种方法
    FPGA按键去抖verilog代码
    DDOS与DDOS追踪的介绍
    自动实时监控Windows2003服务器终端登录
    Java 如何实现线程间通信
    C# 获取FormData数据
    利用 FormData 对象发送 Key/Value 对的异步请求
    jdk初始安装配置
  • 原文地址:https://www.cnblogs.com/shatianming/p/12222836.html
Copyright © 2020-2023  润新知