题目一: Shuttle Puzzle
只能找规律了。。。。
#include <stdio.h> #include <string.h> int n, tot; void display(int m, int st, int s) { for (int j = 1; j <= m; j++, st += s) { if (++tot % 20 == 0) printf("%d/n", st); else printf("%d ", st); } } void PRINT(int m, int min) { int st, s; if (min == 0) return; if (m % 2 == 0) { st = min; s = 2; } else { st = min+(m-1)*2; s = -2; } display(m, st, s); PRINT(m+1, min-1); if (min == 1) return; display(m, st, s); } int main(){ freopen("shuttle.in", "r", stdin); freopen("shuttle.out", "w", stdout); scanf("%d", &n); tot = 0; PRINT(2,n); printf("%d/n", n+1); return 0; }
题目二:Pollutant Control
** Description: 题目实际上要求一个最小割,并且满足经过的边要最少,最后字典序要最小
** Algorithm: MaxFlow(DINIC)
** Analysis: 相当于有三个优先级,流量最高,边数其次,最后是编号
把一条边的权值做如下处理
ww = 500000+i+(long long)500000*1001*w;
500000: 因为边的编号为0..1..2....999 和<500000
1001: 因为最多有1000条边
最后 MaxFlow = MaxFlow'/ (500000*1001)
经过的边数: MaxFlow'%(500000*1001)/500000
割S中的点可以通过FLOODFILLED来求,切记不可直接判断某些边满流即为割
#include <iostream> #include <stdio.h> #include <string.h> #include <cstring> #include <queue> #define MAXE 2000 #define MAXN 40 const long long INF = (long long) 1 << 62; using namespace std; struct E { int u, v; long long f; int next; } e[MAXE]; int M, S, T; int pre[MAXN]; int d[MAXN]; int incut[MAXN]; int head[MAXN], h[MAXN]; void add(int,int,long long); bool BFS(); void DFS(int); long long Dinic(); int main() { freopen("milk6.in", "r", stdin); freopen("milk6.out", "w", stdout); int n, m, i, w; int u[MAXE], v[MAXE]; long long ww, ans; scanf("%d%d", &n, &m); S = 1; T = n; M = 0; memset(head,-1,sizeof(head)); for (i = 0; i < m; i++) { scanf("%d %d %d", &u[i], &v[i], &w); ww = 500000+i+(long long)500000*1001*w; add(u[i], v[i], ww); } ans = Dinic(); memset(incut,0,sizeof(incut)); DFS(S); cout << ans/(500000*1001) <<" "<< ans%(500000*1001)/500000 << endl; for (i = 0; i < m; i++) if (incut[u[i]] && !incut[v[i]]) printf("%d/n", i+1); return 0; } void add(int u, int v, long long f) { e[M].u = u; e[M].v = v; e[M].f = f; e[M].next = head[u]; head[u] = M++; e[M].u = v; e[M].v = u; e[M].f = 0; e[M].next = head[v]; head[v] = M++; // cout << u << " " << v << endl; } bool BFS() { queue<int> Q; while (!Q.empty()) Q.pop(); memset(d,-1,sizeof(d)); d[S] = 0; Q.push(S); while (!Q.empty()) { int x = Q.front(); Q.pop(); for (int i = head[x]; i != -1; i = e[i].next) if (e[i].f && d[e[i].v] == -1) { d[e[i].v] = d[x]+1; if (e[i].v == T) return true; Q.push(e[i].v); } } return false; } long long Dinic() { long long flow, curr; int i, k; bool flag; memset(pre,-1,sizeof(pre)); for (flow = 0; BFS(); ) { memcpy(h, head, sizeof(head)); for (i = S; ; ) { if (i == T) { curr = INF; for (k = pre[T]; k != -1; k = pre[e[k].u]) if (e[k].f < curr) curr = e[k].f; for (k = pre[T]; k != -1; k = pre[e[k].u]) e[k].f -= curr, e[k^1].f += curr; flow += curr; // cout << curr << endl; } for (flag = false, k = h[i]; k != -1; k = e[k].next) if (e[k].f && d[i]+1==d[e[k].v]) { pre[e[k].v] = k; h[i] = k; i = e[k].v; flag = true; break; } if (!flag) { d[i] = -1; if (i == S) break; i = e[pre[i]].u; } } } return flow; } void DFS(int x) { incut[x] = 1; for (int i = head[x]; i != -1; i = e[i].next) if (e[i].f && !incut[e[i].v]) DFS(e[i].v); }
题目三: Frame Up
** Desctiption: 给定矩形字母框的覆盖效果,按字典序求出所有的可能覆盖顺序
** Algorithm: Toposort
** Analysis: 题目保证了四条边框至少有一个点是可见的,所以可以确定每个字母框的范围
然后如果在一个字母框上有其它字母,则连一条有向边,最后TOPO输出
#include <iostream> #include <cstdio> #include <stdio.h> #include <string.h> using namespace std; struct RECT { int x1, y1, x2, y2; bool yes; RECT() { yes = false; x1 = y1 = 100; x2 = y2 = -1; } } rec[26]; bool con[26][26]={0}; char map[40][40]; char path[30] = {0}; int n, m, i, j, cnt, ii, jj; int in[30]={0}; void add(int u, int v) { if (!con[u][v]) { con[u][v] = 1; // printf("%d %d/n", u, v); in[v]++; } } void toposort(int d, int pre) { path[d-1] = 'A'+pre; rec[pre].yes = 0 ; if (d == cnt) { printf("%s/n", path); rec[pre].yes = 1; return; }; for (int i = 0; i < 26; i++) if (con[pre][i]) in[i]--; for (int i = 0; i < 26; i++) if (rec[i].yes&&!in[i]) toposort(d+1, i); for (int i = 0; i < 26; i++) if (con[pre][i]) in[i]++; rec[pre].yes = 1; } int main(){ freopen("frameup.in", "r", stdin); freopen("frameup.out", "w", stdout); scanf("%d %d/n", &n, &m); for (i = 0; i < n; i++) { cin.getline(map[i], 100); for (j = 0; j < m; j++) if (map[i][j] != '.') { int k = map[i][j]-'A'; rec[k].yes = true; if (i < rec[k].x1) rec[k].x1 = i; if (j < rec[k].y1) rec[k].y1 = j; if (i > rec[k].x2) rec[k].x2 = i; if (j > rec[k].y2) rec[k].y2 = j; } } cnt = 0; for (i = 0; i < 26; i++) if (rec[i].yes) { cnt++; int k = 'A'+i; for (ii = rec[i].x1; ii <= rec[i].x2; ii++) { if (map[ii][rec[i].y1] != k) add(i, map[ii][rec[i].y1]-'A'); if (map[ii][rec[i].y2] != k) add(i, map[ii][rec[i].y2]-'A'); } for (jj = rec[i].y1+1; jj <= rec[i].y2-1; jj++) { if (map[rec[i].x1][jj] != k) add(i, map[rec[i].x1][jj]-'A'); if (map[rec[i].x2][jj] != k) add(i, map[rec[i].x2][jj]-'A'); } } // printf("%d/n",cnt); for (i = 0; i < 26; i++) if (rec[i].yes && !in[i]) toposort(1, i);//next is 1, pre is i return 0; }