• UVA11997 K Smallest Sums


    题目

    一句话题意 , 有 k 个长为 k 的序列 , 从其中每个序列选一个数 (k^k) 个和中输出前k小

    考虑 有两个长为n的序列 , 从他们中选出(n)最小的和 , 可以用一个很妙的想法

    在优先队列里 , 存((a_1 + b_1 , 1) , (a_2 + b_1 , 1) , (a_3 + b_1 , 1) dots)

    第一个是 a+b , 第二项是b的下标 , 每次取出最小的 , 然后把 (x - b[id] + b[id] + 1) 放进去(b 是排好序的)

    取 n 遍就行, 而有 k 个的序列的情况两两合并就可以了,正确性贪心可证 ,不写了。。。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N = 756;
    int n;
    int a[N] , b[N];
    priority_queue< pair<int,int> , vector< pair<int,int> > , greater< pair<int,int> > > q; 
    void Merge()
    {
    	while(q.size()) q.pop();
    	for(int i = 1 ; i <= n ; ++i) q.push(make_pair(a[i] + b[1] , 1));
    	int tot = 0;
    	while(q.size())
    	{
    		int x = q.top().first , y = q.top().second; q.pop();
    		a[++tot] = x; if(tot == n) break; 
    		if(y < n) q.push(make_pair(x - b[y] + b[y+1] , y+1));
    	}
    	return ;
    }
    
    int main()
    {
    	while(scanf("%d" , &n) == 1)
    	{
    		for(int i = 1 ; i <= n ; ++i) scanf("%d",&a[i]); // 这里要先读进去一遍a , 不然直接合并就是 n 个 0 与 b 合并 
    		for(int j = 2 ; j <= n ; ++j)
    		{
    			for(int i = 1 ; i <= n ; ++i) scanf("%d",&b[i]);
    			sort(b + 1 , b + 1 + n);
    			Merge();
    		}
    		printf("%d",a[1]);
    		for(int i = 2 ; i <= n ; ++i) printf(" %d" , a[i]); puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    四年的积分数据,反映了信息化的复杂
    Python判断实例对象真与假
    ParameterizedType及其方法详解
    BootStrap的学习
    HTML标签
    CSS样式常见样式
    jQuery的使用
    DOS命令详解
    JavaScript学习
    CSS样式
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12154607.html
Copyright © 2020-2023  润新知