无法用复杂状态进行转移时改变计算方式;巧妙的整体考虑;压缩空间优化时间
传送门:$>here<$
题意
给出一个n*m矩阵,从每一行选一个数加起来,可以得到一个和。易知总共会有$n^n$个和,输出最小的k个。
数据范围:$n,m \leq 800,k \leq m$
Solution
问题的转化
可转化为序列合并问题
启示
问题的转化
转化
my code
第一行要特判
/*By DennyQi 2019*/ #include <cstdio> #include <queue> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 810; const int INF = 0x3f3f3f3f; inline int Max(const int a, const int b){ return (a > b) ? a : b; } inline int Min(const int a, const int b){ return (a < b) ? a : b; } inline int read(){ int x = 0; int w = 1; register char c = getchar(); for(; c ^ '-' && (c < '0' || c > '9'); c = getchar()); if(c == '-') w = -1, c = getchar(); for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w; } int n,m,K; int a[MAXN],b[MAXN],c[MAXN]; priority_queue <int, vector<int>, less<int> > H; inline void Merge(){ while(H.size()) H.pop(); for(int i = 1; i <= m; ++i){ H.push(a[1] + b[i]); } for(int i = 2; i <= m; ++i){ for(int j = 1; j <= m; ++j){ if(a[i]+b[j] < H.top()){ H.pop(); H.push(a[i]+b[j]); } else{ break; } } } for(int i = m; i > 0; --i){ c[i] = H.top(); H.pop(); } } int main(){ n = read(), m = read(), K = read(); for(int i = 1; i <= n; ++i){ for(int j = 1; j <= m; ++j){ a[j] = read(); } sort(a+1,a+m+1); if(i == 1){ for(int j = 1; j <= m; ++j){ b[j] = a[j]; } continue; } Merge(); for(int j = 1; j <= m; ++j){ b[j] = c[j]; } } for(int i = 1; i <= K; ++i){ printf("%d ",b[i]); } return 0; }