标签:最小 ack fine can har img turn next 问题
题意:就是N天,每天可以选择S或者E,每一天S或者E有自己的收益,求最大收益,且满足每个连续K天,只是有Ms天选择了S,Me天选择了E。
输出最大收益,以及对应的方案。
思路:和上一题有点像,不过加了下界,问题不大,直接去看题解就好了。
只需要把相邻的边容量改为最大-最小即可。 对于输出方案,只需要看对应的流是否用掉即可。
#include<bits/stdc++.h> #define ll long long #define maxn 1010 #define inf 1<<30 using namespace std; int To[maxn<<2],Laxt[maxn],Next[maxn<<2],cap[maxn<<2],cost[maxn<<2],tag[maxn]; int N,S,T,cnt=1; ll dis[maxn],ans;//费用 bool inq[maxn],vis[maxn]; deque<int>q; void add(int u,int v,int c,int cc) { Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v;cap[cnt]=c;cost[cnt]=cc; } bool spfa() { memset(inq,0,sizeof(inq)); for(int i=0;i<=T;i++) dis[i]=1LL<<40; inq[T]=1; dis[T]=0; q.push_back(T); while(!q.empty()) { int u=q.front(); q.pop_front(); inq[u]=0; for(int i=Laxt[u];i;i=Next[i]) { int v=To[i]; if(cap[i^1]&&dis[v]>dis[u]-cost[i]) { dis[v]=dis[u]-cost[i]; if(!inq[u]){ inq[v]=1; if(q.empty()||dis[v]>dis[q.front()]) q.push_back(v); else q.push_front(v); } } } } return dis[S]<(1LL<<40); } int dfs(int u,int flow) { vis[u]=1; if(u==T||flow==0) return flow; int tmp,delta=0; for(int i=Laxt[u];i;i=Next[i]) { int v=To[i]; if((!vis[v])&&cap[i]&&dis[v]==dis[u]-cost[i]) { tmp=dfs(v,min(cap[i],flow-delta)); delta+=tmp; cap[i]-=tmp; cap[i^1]+=tmp; } } return delta; } int s[maxn],e[maxn]; int main() { int N,K,mn,mx,ans=0,i; scanf("%d%d%d%d",&N,&K,&mx,&mn); for(i=1;i<=N;i++) scanf("%d",&s[i]),ans+=s[i]; for(i=1;i<=N;i++) scanf("%d",&e[i]),e[i]-=s[i]; mx=K-mx; S=0; T=N+1; add(S,1,mx,0); add(1,S,0,0); for(i=1;i<=N;i++) add(i,i+1,mx-mn,0),add(i+1,i,0,0); for(i=1;i<=N;i++) add(i,i+K>N?T:i+K,1,-e[i]),tag[i]=cnt,add(i+K>N?T:i+K,i,0,e[i]); while(spfa()){ vis[T]=1; while(vis[T]){ memset(vis,0,sizeof(vis)); int tmp=dfs(S,inf); ans-=(ll)tmp*dis[S]; } } printf("%I64d\n",ans); for(i=1;i<=N;i++) if(cap[tag[i]]) putchar(‘S‘); else putchar(‘E‘); return 0; }
Codeforces Gym 101190 NEERC 16 .D Delight for a Cat (上下界的费用流)
标签:最小 ack fine can har img turn next 问题
原文地址:https://www.cnblogs.com/hua-dong/p/9392290.html