您的位置:首页 > 其它

UVA - 11997 K Smallest Sums

2016-05-11 21:17 295 查看
题目链接

题目大意:

有k个整数数组,各包含k个元素,在每个数组中取一个元素加起来,可以得到k的k次方个和。求这些和中最小的k个值。

解题思路:

这个在刘汝佳的大白书P189页是一个例题,有完整的代码。就是先算两个的数组的和,然后依次往后计算,用优先队列存储这些和,然后把最小的加入第一个数组,然后把把新加入的和去掉然后加入下一个和(至于加入哪个和,看代码)。书上说的比较详细,代码中只记录了下标b,书上也有介绍。

题目代码:

#include<iostream>
#include<cstdio>
#include<map>
#include<math.h>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;

int A[800][800];

struct Data
{
int s, b;//存储一个和,和当前的加数的下标
Data(int s, int b):s(s), b(b){}
bool operator < (const Data& pre) const{
return pre.s < s;
}
};

void Merge(int *A, int *B, int * C,int n)
{
priority_queue<Data> q;
int i;
for(i = 0; i < n; i++)
q.push(Data(A[i] + B[0], 0));// 每次先用A[i]加入B[0],这里要注意A,B数组都是从小到大顺序排列的
for(i = 0; i < n; i++)
{
Data t = q.top();//第一个数肯定是一个最小和。也就是A[0] + B[0].
q.pop();
C[i] = t.s;//更新最小的和
int b = t . b;//记录下标
if(b + 1 < n) //加入新的值,关键的一步!!!!
q.push(Data(t.s - B[b] + B[b+1] , b+1));
}
}

int main()
{
int  i, n, j;
while(scanf("%d",&n) != EOF)
{
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
scanf("%d",&A[i][j]);
sort(A[i], A[i] + n);
}
for(i = 1; i < n; i++) // 每次都只算两个
Merge(A[0], A[i], A[0], n);//指针用的很巧妙
for(i = 0; i < n; i++)
{
if(i == n - 1)
printf("%d",A[0][i]);
else
printf("%d ",A[0][i]);
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: