您的位置:首页 > 其它

[费用流]LOJ#6079. 「2017 山东一轮集训 Day7」养猫

2017-10-12 18:29 477 查看

Description

你养了一只猫,为了让它快乐地成长,你需要合理地安排它每天的作息时间。假设一天分为n个时刻,猫在每个时刻要么是吃东西,要么是睡觉。在第i个时刻,假如猫是去吃东西,那么它能获得愉悦值ei​,假如是去睡觉,那么能获得的愉悦值为si 。

猫要成长,不仅仅需要快乐,还需要健康的作息。经过研究,对于每一个连续的长度为k的作息区间,即所有的时刻区间[i,i+k−1],1≤i≤n−k+1,猫都要至少有ms 的时刻用来睡觉,me的时刻用来吃东西,这样猫才能健康成长。

现在你想合理地安排一天中的这n个时刻,使得猫在能健康成长的前提下,获得尽量多的愉悦值。

Solution

**#include <bits/stdc++.h>
using namespace std;

const int INF = 1 << 30;
const int N = 1010;
typedef long long ll;

inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
inline void read(int &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}

struct edge {
int to, next;
int cap, cost;
edge (int t = 0, int n = 0, int c = 0, int co = 0):to(t), next(n), cap(c), cost(co) {}
};
edge G[N << 3];
int head
;
ll dist
;
int vis
, pre
;
int s
, e
;
int ans
;
int Gcnt, n, k, ms, me;
ll Ans;
queue<int> Q;

inline void AddEdge(int from, int to, int cap, int cost) {
G[++Gcnt] = edge(to, head[from], cap, cost); head[from] = Gcnt;
G[++Gcnt] = edge(from, head[to], 0, -cost); head[to] = Gcnt;
}
inline bool SPFA(int S, int T) {
static int x;
memset(dist, 0x3f, sizeof dist);
Q.push(S); dist[S] = 0;
while (!Q.empty()) {
x = Q.front(); Q.pop();
vis[x] = false;
for (int i = head[x]; i; i = G[i].next) {
edge &e = G[i];
if (e.cap && dist[x] + e.cost < dist[e.to]) {
pre[e.to] = i;
dist[e.to] = dist[x] + e.cost;
if (!vis[e.to]) {
vis[e.to] = true; Q.push(e.to);
}
}
}
}
return dist[T] != dist[0];
}
inline ll Flow(int S, int T) {
ll Cost = 0; int f;
while (SPFA(S, T)) {
f = INF;
for (int i = T; i != S; i = G[pre[i] ^ 1].to)
f = min(f, G[pre[i]].cap);
for (int i = T; i != S; i = G[pre[i] ^ 1].to) {
G[pre[i]].cap -= f;
G[pre[i] ^ 1].cap += f;
}
Cost += f * dist[T];
}
return Cost;
}

int main(void) {
freopen("1.in", "r", stdin);
Gcnt = 1;
read(n); read(k); read(ms); read(me);
for (int i = 1; i <= n; i++) read(s[i]);
for (int i = 1; i <= n; i++) read(e[i]);
for (int i = 1; i <= n; i++) {
Ans += s[i]; s[i] -= e[i];
}
for (int i = 1; i <= n; i++) {
if (i + k <= n) AddEdge(i, i + k, 1, s[i]);
else AddEdge(i, n + 2, 1, s[i]);
ans[i] = Gcnt - 1;
if (i < n) AddEdge(i, i + 1, k - ms - me, 0);
else AddEdge(i, n + 2, k - ms - me, 0);
}
AddEdge(n + 1, n + 3, k - ms, 0);
for (int i = 1; i <= k; i++)
AddEdge(n + 3, i, INF, 0);
Ans -= Flow(n + 1, n + 2);
printf("%lld\n", Ans);
for (int i = 1; i <= n; i++)
if (G[ans[i]].cap) putchar('S');
else putchar('E');
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: