训练题(代码未检验)(序列前k大和问题)
大厦
Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 26 Accepted Submission(s) : 7
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
每个房间一定的金钱X(1<=x<=1000),假设不同楼层的房间是互通的,相同楼层的房间是不互通的。也就是说每层只能取一个,现在给你一个捡钱的机会。捡钱的方式不同,会导致你得到的钱的不同,求可能捡到的钱的前k大的和
Input
每组数据第一行输入n,m,k
接下来输入n行,每行m个数,代表这个房间拥有的金钱
Output
Sample Input
1 3 4 5 1 2 3 4 5 6 7 8 1 2 3 4
Sample Output
75
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define ll long long int
#define INF 0x7fffffff
#define mod 1000000007
#define me(a,b) memset(a,b,sizeof(a))
//size_t npos=-1;
using namespace std;
struct Node
{
int a;
int b;
int sum;
friend bool operator<(Node a,Node b)
{
return a.sum<b.sum;
}
};
bool cmp(int a,int b)
{
return a>b;
}
int a[1001][1001];
int ans[1000010];
int main()
{
int t,n,m,k;
int x;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
int cnt=0;
me(a,0);
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<=m;i++)
sort(a[i],a[i]+m,cmp);
me(ans,0);
priority_queue<Node>q;
Node node,temp;
for(int j=0;j<m;j++)
ans[cnt++]=a[0][j];
for(int i=1;i<n;i++)
{
while(!q.empty())
q.pop();
for(int j=0;j<cnt;j++)
{
node.a=ans[j];
node.b=0;
node.sum=ans[j]+a[i][0];
q.push(node);
}
cnt=0;
while(!q.empty())
{
temp=q.top();
q.pop();
ans[cnt++]=temp.sum;
if(cnt>=k)
break;
temp.b++;
temp.sum=temp.a+a[i][temp.b];
q.push(temp);
}
}
int sum=0;
for(int i=0;i<k;i++)
sum+=ans[i];
cout<<sum<<endl;
}
return 0;
}