ZOJ 2561 Order-Preserving Codes
Posted in ZJU OJ on 四月 8th, 2010 by 纳米 – Be the first to comment20??-??-??,阅读题目
2010-04-07,从JBY处问到这题的题解,原来是他那年的集训队作业(NOI08 – IOI09国家集训队)-.-
2010-04-08,发现和我当时的想法和做法一样,好了,我还是太没信心了,为啥不继续调试下去呢-.- 参考JBY的代码,一次AC。
解题报告:
参考《算法艺术与信息学竞赛》P151-152,感觉上此题和那题是类似的,方程也是类似的,可以利用四边形不等式进行优化。
设f(i, j)为第i – j位的最小值,sum(i, j)为第i – j位的和,有:
(1) i=j: f(i, j) = sum(i, i)
(2) i<j: f(i, j) = min{f(i, k) + f(k+1, j) | i <= k < j} + sum(i, j)
这样做的时间复杂度为O(n^3),根据四边形不等式,迅速降为O(n^2),具体不陈述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #include <stdio.h> const int maxn = 2003; int n, data[maxn], o[maxn][maxn]; long long sum[maxn], dp[maxn][maxn]; bool input() { if (scanf("%d", &n) == EOF) return false; for (int i = 1; i <= n; ++i) scanf("%d", &data[i]); return true; } int work() { sum[0] = 0; for (int i = 1; i <= n; ++i) { dp[i][i] = data[i]; o[i][i] = i; sum[i] = sum[i-1] + (long long) data[i]; } for (int l = 2; l <= n; ++l) for (int i = 1, j = l; j <= n; ++i, ++j) { int left = i > o[i][j-1] ? i : o[i][j-1], right = j-1 < o[i+1][j] ? j-1 : o[i+1][j]; dp[i][j] = 0xFFFFFFFFFFFFFFFll; for (int k = left; k <= right; ++k) if (dp[i][k] + dp[k+1][j] < dp[i][j]) { dp[i][j] = dp[i][k] + dp[k+1][j]; o[i][j] = k; } dp[i][j] += sum[j] - sum[i-1]; } return 0; } void output(int x, int l, int r) { if (l >= r) return; if (x <= o[l][r]) { printf("0"); output(x, l, o[l][r]); } else { printf("1"); output(x, o[l][r]+1, r); } } int output() { for (int i = 1; i <= n; ++i) { output(i, 1, n); printf("\n"); } return 0; } int main() { while (input()) { work(); output(); } return 0; } |