51nod 1625夹克爷发红包(贪心+枚举)
2017-10-21 10:14
253 查看
1625 夹克爷发红包
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注
在公司年会上,做为互联网巨头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
题解:本来一开始以为是一旦单纯的比较麻烦的贪心题:每次选择行或者列中收益最大的一列,然后对列或者行信息进行更新。但是有一组数据总是过不了,于是我就开始怀疑算法的正确性,其实没有充分的理由说明这样的贪心是正确的,因为行列直接的彼此影响还是存在的。如果说贪心会错的,那么枚举一定不会错,由于行只有10行,所以枚举行的所有状态,其次在对列进行贪心,显然这样的算法是正确的,而且复杂度不会超时。
对于我这样的菜鸟,感觉这个题还是很考验debug能力的。
注意点:
1.建议全部的变量数组都开long long
2.dfs的退栈处理
代码:
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注
在公司年会上,做为互联网巨头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
题解:本来一开始以为是一旦单纯的比较麻烦的贪心题:每次选择行或者列中收益最大的一列,然后对列或者行信息进行更新。但是有一组数据总是过不了,于是我就开始怀疑算法的正确性,其实没有充分的理由说明这样的贪心是正确的,因为行列直接的彼此影响还是存在的。如果说贪心会错的,那么枚举一定不会错,由于行只有10行,所以枚举行的所有状态,其次在对列进行贪心,显然这样的算法是正确的,而且复杂度不会超时。
对于我这样的菜鸟,感觉这个题还是很考验debug能力的。
注意点:
1.建议全部的变量数组都开long long
2.dfs的退栈处理
代码:
#include<iostream> #include<fstream> #include<string.h> #include<math.h> #include<stdlib.h> #include<stdio.h> #include<utility> #include<algorithm> #include<map> #include<stack> #include<set> #include<queue> using namespace std; typedef long long ll; const int maxn = 1e4+5; const int mod = 1e9+7; const int INF = 1<<30; const ll llINF = 1e18+999; ll n, m, x, k, ans, in[10][200], row[10], tcol[200], col[200];//arr表示每一列或着行替换为 void init( ) { for(int i=0; i<n; i++) { ll sum = 0; for(int j=0; j<m; j++) sum += in[i][j]; row[i] = x*m-sum; } for(int i=0; i<m; i++) { ll sum = 0; for(int j=0; j<n; j++) sum += in[j][i]; col[i] = x*n-sum; } } void dfs(int index, int r, ll sum) { if(index == n)//行已经枚举完毕了,此时对列进行贪心 { memcpy(tcol, col, sizeof(col)); sort(tcol, tcol+m); for(int i=0; i<r&&i<m&&tcol[m-i-1]>0; i++)//此时最多只剩r次替换 sum += tcol[m-i-1]; ans = max(sum, ans); return; } if(r>0) //替换这行 { for(int i=0; i<m; i++) col[i] -= x-in[index][i]; dfs(index+1, r-1, sum+row[index]); for(int i=0; i<m; i++) col[i] += x-in[index][i]; } dfs(index+1, r, sum);//不替换这行 } int main( ) { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); while(~scanf("%lld%lld%lld%lld", &n,&m,&x,&k)) { ans = 0; for(int i=0; i<n; i++) for(int j=0; j<m; j++) { scanf("%lld", &in[i][j]); ans += in[i][j]; } init( ); dfs(0, k, ans); cout<<ans<<endl; } return 0; }
相关文章推荐
- 51NOD 1625 夹克爷发红包 枚举+贪心
- 51nod 1625 夹克爷发红包(状压枚举+贪心)
- 51nod 1625 夹克爷发红包,暴力+贪心
- 51Nod - 1625 夹克爷发红包(暴力+贪心)
- 51 nod 1625 夹克爷发红包【贪心、二进制枚举】
- 51nod 1625 夹克爷发红包【思维+暴力+贪心】好题~
- 51NOD 1625 夹克爷发红包 (贪心+dfs)
- 1625 夹克爷发红包 贪心 + 暴力 + 思维
- 51nod 1625 夹克爷发红包
- 51nod 1625 夹克爷发红包
- 51nod1625 夹克爷发红包 枚举+贪心
- 51nod 1625 夹克爷发红包
- 1625 夹克爷发红包(二进制枚举运用)
- 1625 夹克爷发红包
- 51nod-1380 夹克老爷的逢三抽一(贪心)
- 51Nod-1625-夹克爷发红包
- 51nod 1378 夹克老爷的愤怒(树形DP+贪心)
- 51 Nod 1625 夹克爷发红包
- 51nod 1378 夹克老爷的愤怒(树形dp,贪心)
- 51nod 1378 夹克老爷的愤怒(树型dp+贪心)