bzoj3661
网络流/贪心
网络流做法是对于每一列,如果一个兔子下一天继续可以存在,那么连一条容量为1的边,然后设立一个中转站,来控制可以换的数量,容量限制l。时限100s,能跑过去我的太慢了,一个点100s
正解是贪心。不会证明。每一只兔子,我们当然希望能够尽量连续多跑几天,给其他兔子留机会。每次把在的兔子和不在的兔子排序,具体程序,然后看前l个能不能交换。
巨慢无比的网络流
#include<bits/stdc++.h> using namespace std; const int N = 805 * 805, inf = 1 << 29; struct edge { int nxt, to, f; } e[N * 40]; int n, m, k, l, S1, T, S, cnt = 1; int q[N * 3 + 1621], d[N * 3 + 1621], head[N * 3 + 1621], iter[N * 3 + 1621]; int a[810][810], b[810][810]; #define id(i, j) (i - 1) * m + j inline void link(int u, int v, int f) { e[++cnt].nxt = head[u]; head[u] = cnt; e[cnt].to = v; e[cnt].f = f; } inline void ins(int u, int v, int f) { link(u, v, f); link(v, u, 0); } bool bfs() { int l = 1, r = 0; q[++r] = 0; memset(d, 0, sizeof(d)); d[0] = 1; while(l <= r) { int u = q[l++]; for(int i = head[u]; i; i = e[i].nxt) if(e[i].f && !d[e[i].to]) { d[e[i].to] = d[u] + 1; if(e[i].to == T) return 1; q[++r] = e[i].to; } } return 0; } int dfs(int u, int delta) { if(u == T) return delta; int ret = 0; for(int &i = iter[u]; i && delta; i = e[i].nxt) if(e[i].f && d[e[i].to] == d[u] + 1) { int x = dfs(e[i].to, min(delta, e[i].f)); e[i].f -= x; e[i ^ 1].f += x; ret += x; delta -= x; } d[u] = 0; return ret; } inline int dinic() { int ret = 0; while(bfs()) { for(int i = 0; i <= T; ++i) iter[i] = head[i]; ret += dfs(0, inf); } return ret; } void build() { T = n * m + N * 2 + m * 2 + 2; S1 = n * m + N * 2 + m * 2 + 1; ins(0, S1, k); for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) if(a[i][j]) { ins(id(i, j), id(i, j) + N, 1); b[i][j] = cnt - 1; } for(int i = 1; i <= n; ++i) { if(a[i][1]) ins(S1, id(i, 1), 1); if(a[i][m]) ins(id(i, m) + N, T, 1); } for(int j = 2; j <= m; ++j) ins(n * m + N * 2 + j, n * m + N * 2 + j + m, l); for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) if(a[i][j]) { if(j < m) if(a[i][j + 1]) ins(id(i, j) + N, id(i, j + 1), 1); if(j < m) ins(id(i, j) + N, n * m + N * 2 + j + 1, 1); if(j > 1) ins(n * m + N * 2 + j + m, id(i, j), 1); } } int main() { // freopen("input.txt", "r", stdin); scanf("%d%d%d%d", &n, &m, &k, &l); for(int i = 1; i <= n; ++i) { char s[810]; scanf("%s", s + 1); for(int j = 1; j <= m; ++j) a[i][j] = s[j] - '0'; } build(); int ans = dinic(); if(ans < k) { puts("-1"); return 0; } for(int j = 1; j <= m; ++j) { for(int i = 1; i <= n; ++i) if(b[i][j]) if(e[b[i][j]].f == 0) printf("%d ", i); puts(""); } // fclose(stdin); return 0; }
贪心
#include<bits/stdc++.h> using namespace std; const int N = 810 * 810, inf = 1 << 29; int n, m, k, l; typedef pair<int, int> PII; int pos[810][810], a[810][810], mark[810]; PII b[810][810], c[810][810]; bool cp1(PII x, PII y) { return x.first < y.first; } bool cp2(PII x, PII y) { return x.first > y.first; } int main() { scanf("%d%d%d%d", &n, &m, &k, &l); for(int i = 1; i <= n; ++i) { char s[810]; scanf("%s", s + 1); for(int j = 1; j <= m; ++j) a[i][j] = s[j] - '0'; } for(int j = 1; j <= m; ++j) for(int i = 1; i <= n; ++i) if(a[i][j]) { int Pos = j; b[j][i] = c[j][i] = make_pair(1, i); while(a[i][Pos + 1]) { ++Pos; ++b[j][i].first; ++c[j][i].first; } } sort(b[1] + 1, b[1] + n + 1, cp2); for(int i = 1; i <= k; ++i) if(b[1][i].first > 0) pos[1][++pos[1][0]] = b[1][i].second; if(pos[1][0] < k) { puts("-1"); return 0; } sort(pos[1] + 1, pos[1] + k + 1); for(int i = 1; i <= k; ++i) printf("%d ", pos[1][i]); puts(""); for(int j = 2; j <= m; ++j) { memset(mark, 0, sizeof(mark)); for(int i = 1; i <= k; ++i) mark[pos[j - 1][i]] = 1; for(int i = 1; i <= n; ++i) if(mark[i]) c[j][i].first = -1; else b[j][i].first = inf; sort(b[j] + 1, b[j] + n + 1, cp1); sort(c[j] + 1, c[j] + n + 1, cp2); for(int i = 1; i <= l; ++i) if(b[j][i].first < c[j][i].first) pos[j][i] = c[j][i].second; else pos[j][i] = b[j][i].second; for(int i = l + 1; i <= k; ++i) pos[j][i] = b[j][i].second; sort(pos[j] + 1, pos[j] + k + 1); for(int i = 1; i <= k; ++i) printf("%d ", pos[j][i]); puts(""); } return 0; }