这是我的第七道“差分约束系统”,也是最后计划里的最后一道了,也是最难的一道,经过前几道的联系,看到这个题居然还是毫无思路,没办法,只有查资料了,发现这题居然是所谓的黑书——《算法艺术与信息学竞赛》里面的一道原题,这里就不多说了,截张图看一下算了,因为我实在是也不是很彻底地明白其中的道理。哎.....惭愧.....
贴代码:
/** 第七道差分约束系统 这题比较深奥。。。。。。 详见:《算法艺术与信息学竞赛》 **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXV 30 #define MAXE 1000 #define INF 100000000 struct { int s, e, v; } edge[MAXE]; int neg; int dis[MAXV]; int r[30], t[30], sum; void add(int s, int e, int v) { edge[neg].s = s; edge[neg].e = e; edge[neg].v = v; neg++; } void change(int s) { int i, j; neg = 48; for (j=1; j<=24; j++) { i = (j+7)%24 + 1; if (i > j) add(i, j, -r[i]); else add(i, j, s-r[i]); } add(24, 0, -s); } int relax(int s, int e, int v) { if (dis[s]+v < dis[e]) { dis[e] = dis[s]+v; return 1; } return 0; } int BellmanFord() { int i, j; for (i=0; i<=24; i++) dis[i] = INF; dis[0] = 0; for (i=0; i<=24; i++) for (j=0; j<neg; j++) relax(edge[j].s, edge[j].e, edge[j].v); for (j=0; j<neg; j++) if (relax(edge[j].s, edge[j].e, edge[j].v)) return 0; return 1; } void Bsearch(int low, int high) { int mid = (low+high)/2; if (low > high) return ; change(mid); if (BellmanFord()) { sum = mid; Bsearch(low, mid-1); } else Bsearch(mid+1, high); } int main() { int nc, n, k, i; scanf("%d", &nc); while (nc--) { neg = 0; memset(t, 0, sizeof(t)); for (i=1; i<=24; i++) scanf("%d", &r[i]); scanf("%d", &n); for (i=0; i<n; i++) { scanf("%d", &k); t[k+1]++; } for (i=1; i<=24; i++) { add(i-1, i, t[i]); add(i, i-1, 0); } sum = -1; Bsearch(0, n); if (sum == -1) printf("No Solution\n"); else printf("%d\n", sum); } }