Posts Tagged ‘ZJU OJ’

ZOJ 2561 Order-Preserving Codes

Posted in ZJU OJ on 四月 8th, 2010 by 纳米 – Be the first to comment

20??-??-??,阅读题目
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;
}