1. 程式人生 > >訓練題(代碼未檢驗)(序列前k大和問題)

訓練題(代碼未檢驗)(序列前k大和問題)

desc esc end limit times clu 一個 using ble

大廈

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

給你一個n(1<=n<=1000)層樓的大廈,每一樓裏面有m(1<=m<=1000)房間,
每個房間一定的金錢X(1<=x<=1000),假設不同樓層的房間是互通的,相同樓層的房間是不互通的。也就是說每層只能取一個,現在給你一個撿錢的機會。撿錢的方式不同,會導致你得到的錢的不同,求可能撿到的錢的前k大的和

Input

輸入一個T,表示T組樣例;
每組數據第一行輸入n,m,k
接下來輸入n行,每行m個數,代表這個房間擁有的金錢

Output

輸出可能撿到的錢的前k大的和

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;
}

訓練題(代碼未檢驗)(序列前k大和問題)