NC214521. 请问您要来点兔子吗?
描述
智乃酱的店中有一排 n 只兔子,智乃酱想要从中选出一些兔兔参加比赛。每一只兔子都有一个能力值 ,这个能力值有正有负,由于智乃酱不想让选出的兔子分布过于集中或者分散,她规定每连续的 k 只兔子中至少要选 L 只,至多选 R 只。例如 当 n=5, k=2, L=1, R=2时 ,表示如下的限制条件
1、第 1 只和第 2 只兔子中至少选 1 只参加比赛,至多选 2 只参加比赛。
2、第2只和第 3 只兔子中至少选 1 只参加比赛,至多选 2 只参加比赛。
3、第 3 只和第 4 只兔子中至少选 1 只参加比赛,至多选 2 只参加比赛。
4、第 4 只和第 5 只兔子中至少选 1 只参加比赛,至多选 2 只参加比赛。
请问智乃酱能够选出兔子的能力值之和最大为多少?
输入描述
第一行输入一个正整数 T,表示有 T 组测试案例。
对于每组测试样例:
首先输入一个正整数
接下来一行 n 个整数
接下来一行输入三个正整数所有测试数据的 n 之和小于 300000##
输出描述
仅一行一个整数,表示所选兔子能力值的最大和。
示例1
输入:
4 5 1 2 3 4 5 2 0 1 8 6 9 8 5 4 3 8 4 5 2 4 10 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 1 1 1 10 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 1 0 1
输出:
9 43 -55 0
C++(g++ 7.5.0) 解法, 执行用时: 95ms, 内存消耗: 560K, 提交时间: 2022-10-05 03:17:23
#include<bits/stdc++.h> #define int long long #define pii pair<int,int> using namespace std; namespace dinic { const int N=505; const int inf=1e18; int S,T,MAXn; int v[N],dis[N],lst[N]; struct node{int to,val,w,rev;}; vector <node> e[N]; void add(int x,int y,int z,int w) { e[x].push_back((node){y,z,w,(int)e[y].size()}); e[y].push_back((node){x,0,-w,(int)e[x].size()-1}); } bool SPFA() { for(int i=0;i<=MAXn;++i)dis[i]=inf , lst[i]=v[i]=0; //memset(lst,0,sizeof(lst)); //for(int i=0;i<N;i++) dis[i]=inf; queue <int> q;dis[S]=0,v[S]=1,q.push(S); while(q.size()) { int x=q.front();q.pop(),v[x]=0; for(const auto &i:e[x]) if(dis[i.to]>dis[x]+i.w&&i.val>0) { dis[i.to]=dis[x]+i.w; if(!v[i.to]) v[i.to]=1,q.push(i.to); } } return dis[T]!=inf; } int dfs(int x,int flow) { if(x==T) return flow;int sum=0;v[x]=1; for(int &i=lst[x];i<e[x].size();i++) { int t=e[x][i].to,val=e[x][i].val,w=e[x][i].w,r=e[x][i].rev; if(dis[t]!=dis[x]+w||val<=0||v[t]) continue; int Q=dfs(t,min(flow,val)); sum+=Q,flow-=Q,e[x][i].val-=Q,e[t][r].val+=Q; if(!flow) break; } v[x]=0;if(!sum) dis[x]=inf;return sum; } pii FYL() { int ans1=0,ans2=0; while(SPFA()){int x=dfs(S,inf);ans1+=x,ans2+=x*dis[T];} return {ans1,ans2}; } /*int n,m; void MUBAN() { scanf("%lld%lld",&n,&m); S=1 , T=n , MAXn=n; for(int i=1;i<=m;i++) { int x,y,z,w; scanf("%lld%lld%lld%lld",&x,&y,&z,&w); add(x,y,z,w); } pii ans=FYL(); printf("%lld %lld",ans.first,ans.second); }*/ int n; int k,L,R; int a[N]; void init() { scanf("%lld",&n); for(int i=1;i<=n;++i)scanf("%lld",&a[i]); scanf("%lld%lld%lld",&k,&L,&R); for(int u=0;u<=MAXn;++u)e[u].clear(); S=n+1 , T=S+1 , MAXn=T; } void Build() { add(S,1,R,-0);// , add(n,T,inf,-0); //for(int u=1;u<n;++u)add(u,u+1,R-L,-0); add(n,T,R-L,-0); for(int u=1;u<n;++u) { if(u<k)add(u,u+1,inf,-0); else add(u,u+1,R-L,-0); } for(int u=1;u<=n;++u) { int v = (u+k<=n) ? u+k : T; add(u,v,1,-a[u]); } } void work()//最大费用最大流 { init(); Build(); pii res=FYL(); printf("%lld\n",-res.second); } } signed main() { int TTT;scanf("%lld",&TTT);while(TTT--)dinic::work(); return 0; }
C++(clang++11) 解法, 执行用时: 149ms, 内存消耗: 784K, 提交时间: 2020-12-18 11:37:18
#include <bits/stdc++.h> using namespace std; #define N 505 #define INF 1000000009 int n,K,L,R,l=1,S,T; int to[N<<2],h[N<<2],s[N],c[N<<2],w[N<<2],a[N],dist[N],mn[N],pre[N],vis[N]; struct node { int x; bool friend operator < (node A,node B){ return dist[A.x]>dist[B.x]; } }p; priority_queue<node >Q; void hah(int x,int y,int z,int t){ to[++l]=y,h[l]=s[x],s[x]=l,c[l]=z,w[l]=t; to[++l]=x,h[l]=s[y],s[y]=l,c[l]=-z,w[l]=0; } bool SPFA(){ for(int i=1;i<=n+2;i++)mn[i]=dist[i]=INF; dist[S]=0; Q.push({S}); while(!Q.empty()){ p=Q.top(); Q.pop(); vis[p.x]=0; for(int i=s[p.x];i;i=h[i]){ if(w[i] && dist[to[i]]>dist[p.x]+c[i]){ dist[to[i]]=dist[p.x]+c[i]; mn[to[i]]=min(mn[p.x],w[i]); pre[to[i]]=i; if(!vis[to[i]]){ Q.push({to[i]}); vis[to[i]]=1; } } } } if(dist[T]==INF)return false; else return true; } int MCMF(){ int ans=0; while(SPFA()){ int x=T; while(x!=S){ int tmp=pre[x]; w[tmp]-=mn[T]; w[tmp^1]+=mn[T]; x=to[tmp^1]; } ans+=dist[T]*mn[T]; } return ans*(-1); } int main(){ int t; scanf("%d",&t); while(t--){ l=1; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); scanf("%d%d%d",&K,&L,&R); S=n+2,T=n+1; hah(S,1,0,R); for(int i=1;i<=n;i++){ if(i<K)hah(i,i+1,0,INF); else hah(i,i+1,0,R-L); hah(i,min(i+K,T),-a[i],1); } printf("%d\n",MCMF()); for(int i=1;i<=n+2;i++)s[i]=0; } }