luoguP1251 餐巾计划问题

Posted shxnb666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP1251 餐巾计划问题相关的知识,希望对你有一定的参考价值。

题目:

https://www.luogu.org/problemnew/show/P1251

题解:

原来的想法不行:算费用的时候算的是一条餐巾的,但对于重复使用多天的餐巾不公平,因为他们的费用肯定比用一次的大,但是它们贡献也大。

两种想法:

->平均费用 不可做。

->这一次费用 可做。

嘿嘿,还挺有意思的。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<queue>
#include<cstdlib>
#define LL long long
#define N 10000
#define INF 1000000007
#define S 0
#define T (2*n+1)
#define ri register int
using namespace std;

int n,cc;
int r[N],p0,t1,p1,t2,p2;

int cr(int x)
  return 2*n+x+1;


struct graph 
  vector<int> to,w,c;
  vector<int> ed[N];
  LL dis[N]; int cur[N];
  bool vis[N];
  
  void add_edge(int a,int b,int aw,int ac) 
    to.push_back(b); w.push_back(aw); c.push_back(ac);  ed[a].push_back(to.size()-1);
    to.push_back(a); w.push_back(0);  c.push_back(-ac); ed[b].push_back(to.size()-1);
  
  
  bool spfa() 
    memset(dis,0x2f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int> q;
    dis[S]=0;q.push(S);vis[S]=1;
    while (!q.empty()) 
      int x=q.front(); q.pop();
      //printf("%d %d %lld\n",cc,x,dis[x]);
      for (ri i=0;i<ed[x].size();i++) 
        int e=ed[x][i];
        if (dis[to[e]]>dis[x]+c[e] && w[e]) 
          dis[to[e]]=dis[x]+c[e];
          if (!vis[to[e]]) vis[to[e]]=1,q.push(to[e]);
        
      
      vis[x]=0;
    
    return dis[T]<INF;
  
  int dfs(int x,int lim) 
    if (x==T || !lim) return lim;
    LL sum=0; vis[x]=1;
    for (ri &i=cur[x];i<ed[x].size();i++) 
      int e=ed[x][i];
      if (dis[x]+c[e]==dis[to[e]] && w[e] && !vis[to[e]]) 
        int f=dfs(to[e],min(lim,w[e]));
        w[e]-=f; w[1^e]+=f;
        lim-=f; sum+=f;
        if (!lim) return sum;
      
    
    return sum;
  
  LL zkw() 
    LL ret=0;
    cc=1;
    while (spfa()) 
      memset(vis,0,sizeof(vis));
      memset(cur,0,sizeof(cur));
      int t=dfs(S,INF);
      ++cc;
      ret+=t*dis[T];
    
    return ret;
  
 G;

int main() 
  scanf("%d",&n);
  for (ri i=1;i<=n;i++) scanf("%d",&r[i]);
  scanf("%d %d %d %d %d",&p0,&t1,&p1,&t2,&p2);
  for (ri i=1;i<=n;i++) G.add_edge(S,n+i,r[i],0);
  for (ri i=1;i<=n;i++) G.add_edge(i,T,r[i],0);
  for (ri i=1;i<n;i++)  G.add_edge(n+i,n+i+1,INF,0);
  for (ri i=1;i<=n;i++) 
    if (i+t1<=n) G.add_edge(n+i,i+t1,INF,p1);
    if (i+t2<=n) G.add_edge(n+i,i+t2,INF,p2);
  
  for (ri i=1;i<=n;i++) G.add_edge(S,i,INF,p0);
  printf("%lld\n",G.zkw());
  return 0;

以上是关于luoguP1251 餐巾计划问题的主要内容,如果未能解决你的问题,请参考以下文章

P1251 餐巾计划问题

P1251 餐巾计划问题

P1251 餐巾计划问题

洛谷 P1251 餐巾计划问题(线性规划网络优化)费用流

P1251 餐巾计划问题 (费用流)

P1251 餐巾计划 (网络流)