2939 Delight for a Cat
ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜,因此一个小时内他只能选择睡觉或者打隔膜,当然他也必须选择睡觉或打隔膜,对于每一个小时,他选择睡觉或打隔膜的愉悦值是不同的,对于第i个小时,睡觉的愉悦值为si,打隔膜的愉悦值为ei,同时又有一个奥妙重重的规定:对于任意一段连续的k小时,ls必须至少有t1时间在睡觉,t2时间在打隔膜。那么ls想让他获得的愉悦值尽量大,他该如何选择呢?
输入
第一行四个整数,n,k(1<=k<=n<=1000),t1,t2(0<=t1,t2<=k;t1+t2<=k),含义如上所述。
接下来一行n个整数,第i个整数si(0<=si<=1e9)表示睡觉的愉悦值。
接下来一行n个整数,第i个整数ei(0<=ei<=1e9)表示打隔膜的愉悦值。
输出
第一行输出最大的愉悦值。
接下来一行输出一个长度为n的字符串
第i个字符为E则代表第i小时在打隔膜,第i个字符为S则代表第i个小时在睡觉。
数据范围
27% 2 <= n <= 90 2 <= k <= 15
40% 2 <= n <= 500 2 <= k <= 65
100% 2 <= n <= 1000 2 <= k <= 1000
输入样例
输入样例1:
10 4 1 2
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
输入样例2:
1 1 0 1
992949351
743176969
输入样例3:
2 2 1 0
738091870 236758424
921608564 874185073
输出样例
输出样例1:
69
EEESESEESS
输出样例2:
743176969
E
输出样例3:
1612276943
SE
解析:
首先当睡觉或者打隔膜任意一个活动满足其时间条件时,另一个也一定满足时间条件。
1.先考虑打隔膜的时间必须为t2时怎么解决。
设起初所有时间都在睡觉,那么我们需要这个睡觉的权值和-最小的sigma( si-ei )。
对每第i个点向第i+k个点引一条边,不存在则引向结尾的点,流量为1,消费为si-ei。(这条边表示第 i 小时选择了打隔膜)
虚点引到[ 1 , k ]点各一条边,流量无限,消费为0。 起始点引向虚点一条边,流量为t2。
这样建图保证了第i个点和第i+k个点一定一起取,从而保证了每个区间最后都一定有t2个时间在打隔膜(可以证明 : 必须有t2个时间打隔膜时,一定有i和i+k一起取)。
2.现在考虑可以随意使用的k-t1-t2个时间。
对第i个点向第i+1个点引一条边,流量为k-t1-t2,消费为0。此时起始点向虚点的边流量应变为k-t1。
显然有t2条路的选择和1中的没有什么分别。但i到i+1的路和起始点更多的流量给选择更多的打隔膜边留下了机会,我们还可以在每个k区间多选k-t1-t2条打隔膜边。
放代码:
#include<bits/stdc++.h>
#define maxn 1005
#define maxm 10005
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
int n,K,t1,t2;
LL s[maxn],e[maxn],cst[maxm],h[maxn],ans;
int S,T,buf[maxn],info[maxn],Prev[maxm],to[maxm],cap[maxm],vis[maxn],id[maxn],cnt_e=1;
void Node(int u,int v,int c,LL ct){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cap[cnt_e]=c,cst[cnt_e]=ct; }
void Line(int u,int v,int c,LL ct){
Node(u,v,c,ct),Node(v,u,0,-ct);
}
bool SPFA(){
static queue<int>q;
static bool inq[maxn];
memcpy(info,buf,sizeof info);
memset(h,-0x3f,sizeof h);
q.push(T),h[T]=0;
for(int u;!q.empty();){
u=q.front(),q.pop();
for(int i=info[u],v;i;i=Prev[i]) if(cap[i^1] && h[v=to[i]] < h[u] + cst[i^1]){
h[v] = h[u] + cst[i^1];
if(!inq[v]) inq[v]=1,q.push(v);
}
inq[u]=0;
}
return h[S] > h[0];
}
int aug(int u,int mx){
if(u == T) return ans+=mx*h[S],mx;
int st = mx , inc;vis[u] = 1;
for(int &i=info[u],v;i;i=Prev[i]) if(cap[i] && h[v=to[i]] + cst[i] == h[u] && !vis[v]){
inc = aug(v,min(cap[i] , st));
st -= inc , cap[i] -= inc , cap[i^1] += inc;
if(!st) return vis[u] = 0,mx;
}
vis[u] = 0;
return mx - st;
}
int main(){
scanf("%d%d%d%d",&n,&K,&t1,&t2);
for(int i=1;i<=n;i++) scanf("%lld",&s[i]),ans+=s[i];
for(int i=1;i<=n;i++) scanf("%lld",&e[i]),Line(i,min(i+K,n+1),1,e[i]-s[i]),id[i]=cnt_e;
for(int i=1;i<=n;i++) Line(i,i+1,K-t1-t2,0);
Line(S=n+3,n+2,K-t1,0);T = n+1;
for(int i=1;i<=K;i++) Line(n+2,i,inf,0);
for(memcpy(buf,info,sizeof info);SPFA();) aug(S,inf);
printf("%lld\n",ans);
for(int i=1;i<=n;i++)
if(cap[id[i]]) putchar('E');
else putchar('S');
return 0;
}