标签:http io ar for cti sp 代码 on c
题目:UVA11997K Smallest Sums(优先队列+二路归并)
题目大意:求K个最小和。给出K行,每行有K个数,在每行中取一个元素相加,求这些和中最小的k的值。
解题思路:每一行排列一下,那么对于两张表a1< a2 < a3 < a4... ,可以将a1 + b1(最小的), a1+ b2, a1 + b3...a1 + bk存到优先队列中,然后最小的出队,就尝试将剩余和中
b1 < b2 < b3 < b4...
相应较小的存入优先队列,b1 + a2。求这个数值的时候,只需要知道a的下标就可以求到。s1 = a1 + b1 , s2 = b1 + a1 - a1 + a2 = s1 - a1 + a2。碰到K个表就将表两两二路归并。
代码:
#include <cstdio> #include <queue> #include <algorithm> using namespace std; const int N = 755; int k; struct Item { int s, b; //Item () {} Item (int s, int b): s(s), b(b) {} bool operator < (const Item &a) const { return s > a.s; } }; priority_queue<Item> q; void merge (int *A, int *B, int *C) { while (!q.empty()) { q.pop(); } for (int i = 0; i < k; i++) q.push (Item (A[i] + B[0], 0)); for (int i = 0; i < k; i++) { Item item = q.top(); q.pop(); C[i] = item.s; if (item.b + 1 < k) q.push (Item (item.s - B[item.b] + B[item.b + 1], item.b + 1)); } } int main () { int A[N][N]; while (scanf ("%d", &k) != EOF) { for (int i = 0; i < k; i++) { for (int j = 0; j < k; j++) scanf ("%d", &A[i][j]); sort (A[i], A[i] + k); } for (int i = 1; i < k; i++) merge (A[0], A[i], A[0]); for (int i = 0; i < k - 1; i++) printf ("%d ", A[0][i]); printf ("%d\n", A[0][k - 1]); } return 0; }
UVA11997K Smallest Sums(优先队列+二路归并)
标签:http io ar for cti sp 代码 on c
原文地址:http://blog.csdn.net/u012997373/article/details/39151671