poj2442 Sequence

很神的一道题。

我的想法一开始是把这m个序列排序取差分,然后把每个队的第一个差分入堆。

每次取堆顶,同时把该队下一个差分入堆。

后来看了书,仔细思考一下自己的算法发现问题大得很。

因为我的算法在一组之中选了第二个数就不能选回第一个了。

然后我们观察书本:NB!

首先考虑只有2个序列:

若选了(i, j),那么下一个解只可能来源于(i + 1, j) || (i, j + 1)

这样我们就可以cdnqcfm_x@$74QR32Q5(&)*^\L(一通骚操作) 了。

注意:(1, 2) && (2, 1) 都有可能引出(2, 2)故我们规定(2, 2)只能由(2, 1)引出。

即获得(i, j)的顺序必须是:(1, 1) -> (i, 1) -> (i, j)

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <queue>
 4 /// poj 2442
 5 const int N = 2010;
 6 struct A {
 7     int a[N];
 8     inline void st(int k) {
 9         std::sort(a + 1, a + k + 1);
10         return;
11     }
12 }a[110];
13 
14 struct ForQ {
15     int i, j, val;
16     bool j_use;
17     bool operator > (const ForQ &x) const {
18         return val > x.val;
19     }
20 };
21 
22 std::priority_queue<ForQ, std::vector<ForQ>, std::greater<ForQ> > Q;
23 
24 ForQ mk(int i, int j, int val, bool f) {
25     ForQ ans;
26     ans.i = i;
27     ans.j = j;
28     ans.val = val;
29     ans.j_use = f;
30     return ans;
31 }
32 
33 int main() {
34     int T;
35     scanf("%d", &T);
36     while(T--) {
37         int m, n;
38         scanf("%d%d", &m, &n);
39         for(int i = 1; i <= m; i++) {
40             for(int j = 1; j <= n; j++) {
41                 scanf("%d", &a[i].a[j]);
42             }
43         }
44         for(int i = 1; i <= m; i++) {
45             a[i].st(n);
46         }
47         for(int c = 2; c <= m; c++) {
48             int i = 1, j = 1;
49             while(!Q.empty()) Q.pop();
50             Q.push(mk(1, 1, a[1].a[1] + a[c].a[1], 0));
51             for(int i = 1; i <= n; i++) {
52                 ForQ t = Q.top();
53                 Q.pop();
54                 a[0].a[i] = t.val;
55                 Q.push(mk(t.i, t.j + 1, a[1].a[t.i] + a[c].a[t.j + 1], 1));
56                 if(!t.j_use) {
57                     Q.push(mk(t.i + 1, t.j, a[1].a[t.i + 1] + a[c].a[t.j], 0));
58                 }
59             }
60             for(int i = 1; i <= n; i++) {
61                 a[1].a[i] = a[0].a[i];
62             }
63         }
64         for(int i = 1; i <= n; i++) {
65             printf("%d ", a[1].a[i]);
66         }
67         printf("\n");
68     }
69     return 0;
70 }
AC代码

 

posted @ 2018-05-23 18:20  garage  阅读(104)  评论(0编辑  收藏  举报