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 }