51nod 1625 贪心/思维
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1625
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
![](http://file.51nod.com/images/icon/star.png)
![](http://file.51nod.com/images/icon/plus.png)
在公司年会上,做为互联网巨头51nod掌门人的夹克老爷当然不会放过任何发红包的机会。
现场有n排m列观众,夹克老爷会为每一名观众送出普通现金红包,每个红包内金额随机。
接下来,夹克老爷又送出最多k组高级红包,每组高级红包会同时给一排或一列的人派发 ,每个高级红包的金额皆为x。
派发高级红包时,普通红包将会强制收回。同时,每个人只能得到一个高级红包。(好小气!)
现在求一种派发高级红包的策略,使得现场观众获得的红包总金额最大。
Input
第一行为n, m, x, k四个整数。 1 <= n <= 10, 1 <= m <= 200 1 <= x <= 10^9,0 <= k <= n + m 接下来为一个n * m的矩阵,代表每个观众获得的普通红包的金额。普通红包的金额取值范围为1 <= y <= 10^9
Output
输出一个整数,代表现场观众能获得的最大红包总金额
Input示例
3 4 1 5 10 5 7 2 10 5 10 8 3 9 5 4
Output示例
78
还有这种操作,贪心半天发现会有后效性,后来看题解说枚举行状态我才明白过来= =,将行状态固定之后再去贪心的更新列状态找到最大值就方便多了。
万恶的bug竟是因为我用s1记录已经发过了几行红包,更新列的时候直接 (int j=s1;j<=k;++j) ,特喵的相当于赠送了一个红包,检查了半天我也是服气!
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 LL e[15][205]; 5 LL r[15]; 6 LL o[205]; 7 int main() 8 { 9 LL n,m,x,k,i,j; 10 cin>>n>>m>>x>>k; 11 for(i=1;i<=n;++i) 12 { 13 for(j=1;j<=m;++j) 14 { 15 scanf("%lld",&e[i][j]); 16 r[i]+=e[i][j]; 17 } 18 } 19 for(i=1;i<=m;++i) 20 for(j=1;j<=n;++j) 21 o[i]+=e[j][i]; 22 LL ans=0; 23 for(i=0;i<(1<<(n));++i) 24 { 25 LL s1=0,s2=0; 26 for(j=1;j<=n;++j) 27 { 28 if(i&(1<<(j-1))){ 29 s1++; 30 s2+=x*m; 31 } 32 else s2+=r[j]; 33 } 34 if(s1>k) continue; 35 priority_queue<LL,vector<LL>,greater<LL> >q; 36 37 for(j=1;j<=m;++j) 38 { 39 LL fro=o[j]; 40 for(LL c=1;c<=n;++c) 41 if(i&(1<<(c-1))) {fro+=(x-e[c][j]);} 42 q.push(fro); 43 } 44 for(j=s1+1;j<=k;++j) 45 { 46 LL t=q.top(); 47 if(t>x*n||q.empty()) break; 48 else{ 49 s2+=(x*n-t); 50 q.pop(); 51 } 52 53 } 54 ans=max(ans,s2); 55 56 } 57 cout<<ans<<endl; 58 return 0; 59 } 60 /* 61 附上一组数据 62 3 3 30 2 63 10 10 10 64 1 1 99 65 20 20 99 66 388 67 */