標籤:problems memset 正整數 lin ini put discus class sea
1283: 序列Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 272 Solved: 151
[Submit][Status][Discuss]Description給出一個長度為 的正整數序列Ci,求一個子序列,使得原序列中任意長度為 的子串中被選出的元素不超過K(K,M<=100) 個,並且選出的元素之和最大。Input第1行三個數N,m,k。 接下來N行,每行一個字串表示Ci。Output最大和。Sample Input10 5 3
4 4 4 6 6 6 6 6 4 4
Sample Output30
HINT
20%的資料:n<=10。
100%的資料:N<=1000,k,m<=100。Ci<=20000。
Source
By YM
[Submit][Status][Discuss]
最大費用最大流
設立一個源點,一個匯點,源點向1連$<s,1,k,0>$的邊(分別是出點,入點,流量,費用),n向匯點連$<n,t,k,0>$的邊,1到n也用$<i,i+1,k,0>$的邊連起來,限制最多流過k個流量。
1到n每個點$i$向$i+m$連一條$<i,i+m,1,num_{i}>$的邊,表示選擇這個數字,下次該流最少需要在$i+m$點之後選擇下一個選擇的數字。如果$i+m \gt n$,就向匯點連。
1 #include <bits/stdc++.h> 2 3 const int inf = 1e9; 4 const int siz = 20005; 5 6 int n, m, k, num[siz]; 7 8 int s, t; 9 int hd[siz];10 int to[siz];11 int fl[siz];12 int vl[siz];13 int nt[siz];14 15 inline void add(int u, int v, int f, int w)16 {17 static int edge = 0, init = 1;18 if (init)memset(hd, -1, sizeof(hd)), init = 0;19 nt[edge] = hd[u]; to[edge] = v; fl[edge] = f; vl[edge] = +w; hd[u] = edge++;20 nt[edge] = hd[v]; to[edge] = u; fl[edge] = 0; vl[edge] = -w; hd[v] = edge++;21 }22 23 int pre[siz];24 int dis[siz];25 26 inline bool spfa(void)27 {28 static int que[siz], inq[siz], head, tail;29 for (int i = s; i <= t; ++i)dis[i] = -inf;30 memset(inq, 0, sizeof(inq));31 head = 0, tail = 0;32 que[tail++] = s;33 pre[s] = -1;34 dis[s] = 0;35 36 while (head != tail)37 {38 int u = que[head++], v; inq[u] = 0;39 40 for (int i = hd[u]; ~i; i = nt[i])41 if (dis[v = to[i]] < dis[u] + vl[i] && fl[i]) {42 dis[v] = dis[u] + vl[i], pre[v] = i ^ 1;43 if (!inq[v])inq[que[tail++] = v] = 1;44 }45 }46 47 return dis[t] > -inf;48 }49 50 inline int maxCost(void)51 {52 int cost = 0;53 54 while (spfa())55 {56 int flow = inf;57 58 for (int i = pre[t]; ~i; i = pre[to[i]])59 if (flow > fl[i ^ 1])flow = fl[i ^ 1];60 61 for (int i = pre[t]; ~i; i = pre[to[i]])62 fl[i] += flow, fl[i ^ 1] -= flow;63 64 cost += flow * dis[t];65 }66 67 return cost;68 }69 70 signed main(void)71 {72 scanf("%d%d%d", &n, &m, &k);73 74 for (int i = 1; i <= n; ++i)75 scanf("%d", num + i);76 77 s = 0, t = n + 1;78 79 add(s, 1, k, 0);80 add(n, t, k, 0);81 82 for (int i = 1; i < n; ++i)83 add(i, i + 1, k, 0);84 85 for (int i = 1; i <= n; ++i)86 if (i + m <= n)87 add(i, i + m, 1, num[i]);88 else89 add(i, t, 1, num[i]);90 91 printf("%d\n", maxCost());92 }
@Author: YouSiki
BZOJ 1283: 序列