51nod 1625 夹克爷发红包
2017-11-10 19:38
197 查看
在公司年会上,做为互联网巨头51nod掌门人的夹克老爷当然不会放过任何发红包的机会。
现场有n排m列观众,夹克老爷会为每一名观众送出普通现金红包,每个红包内金额随机。
接下来,夹克老爷又送出最多k组高级红包,每组高级红包会同时给一排或一列的人派发 ,每个高级红包的金额皆为x。
派发高级红包时,普通红包将会强制收回。同时,每个人只能得到一个高级红包。(好小气!)
现在求一种派发高级红包的策略,使得现场观众获得的红包总金额最大。
Input
Output
Input示例
Output示例
78
其实具体还不是特别明白,先写下来.
首先利用二进制的特性来枚举行,对于行来说在把列的情况暴力求出来,之后选择最优情况
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#define LL long long
using namespace std;
const int MAXN = 11;
const int MAXM = 201;
LL money[MAXN][MAXM];
int rlist[MAXN];
vector<LL> rowSum;
vector<LL> colSum;
vector<LL> h; // 替换完行后,存储替换列的收益
// 检索第i种组合使用了几组高级红包
int count(int num)
{
int ret = 0;
while (num)
{
if (num & 1)
{
ret++;
}
num >>= 1;
}
return ret;
}
bool cmp(const LL &a, const LL &b)
{
return a > b;
}
int main()
{
LL n, m, x, k;
LL sum = 0; // 所有红包总和
scanf("%lld %lld %lld %lld", &n, &m, &x, &k);
rowSum.resize(n, 0);
colSum.resize(m, 0);
h.resize(m, 0);
for (int i = 0; i < n; ++ i)
{
for (int j = 0; j < m; ++ j)
{
scanf("%lld", &money[i][j]);
rowSum[i] += money[i][j];
colSum[j] += money[i][j];
sum += money[i][j];
}
}
LL row_max = 1ll * x * m; // 整行为高级红包
LL col_max = 1ll * x * n; // 整列为高级红包
LL ans = sum; // 初始为sum
for (int i = 0; i < (1 << n); i++) // 枚举所有行的组合 (1 << n)种组合
{
LL ret = sum;
int idx = 0;
int cnt = count(i); // 高级红包使用组数
if (k < cnt) // 如果超过了k,肯定不行,因为最多发k组
{
continue;
}
for (int j = 0; j < n; ++j)
{
if (i & (1 << j)) // 为1的标示这一行替换固定红包x,求出收益,并标示替换了哪些行
{
ret += row_max - rowSum[j];
rlist[idx++] = j; // 记录高级红包发放行数
}
}
for (int j = 0; j < m; ++j) // 求出替换完行后,每一列如果被替换所得的收益
{
h[j] = col_max - colSum[j];
for (int l = 0; l < idx; ++l)
{
h[j] += money[rlist[l]][j] - x;
}
}
sort(h.begin(), h.end(), cmp); // 根据收益大小排序,得到最大收益的列的顺序
for (int j = 0; j + cnt < k && h[j] > 0; ++j) // k-cnt剩余的就通过替换列来补充,直接加上列的收益即可
{
ret += h[j];
}
ans = max(ans, ret); // 更新最大收益
}
printf("%lld\n", ans);
return 0;
}
现场有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
其实具体还不是特别明白,先写下来.
首先利用二进制的特性来枚举行,对于行来说在把列的情况暴力求出来,之后选择最优情况
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#define LL long long
using namespace std;
const int MAXN = 11;
const int MAXM = 201;
LL money[MAXN][MAXM];
int rlist[MAXN];
vector<LL> rowSum;
vector<LL> colSum;
vector<LL> h; // 替换完行后,存储替换列的收益
// 检索第i种组合使用了几组高级红包
int count(int num)
{
int ret = 0;
while (num)
{
if (num & 1)
{
ret++;
}
num >>= 1;
}
return ret;
}
bool cmp(const LL &a, const LL &b)
{
return a > b;
}
int main()
{
LL n, m, x, k;
LL sum = 0; // 所有红包总和
scanf("%lld %lld %lld %lld", &n, &m, &x, &k);
rowSum.resize(n, 0);
colSum.resize(m, 0);
h.resize(m, 0);
for (int i = 0; i < n; ++ i)
{
for (int j = 0; j < m; ++ j)
{
scanf("%lld", &money[i][j]);
rowSum[i] += money[i][j];
colSum[j] += money[i][j];
sum += money[i][j];
}
}
LL row_max = 1ll * x * m; // 整行为高级红包
LL col_max = 1ll * x * n; // 整列为高级红包
LL ans = sum; // 初始为sum
for (int i = 0; i < (1 << n); i++) // 枚举所有行的组合 (1 << n)种组合
{
LL ret = sum;
int idx = 0;
int cnt = count(i); // 高级红包使用组数
if (k < cnt) // 如果超过了k,肯定不行,因为最多发k组
{
continue;
}
for (int j = 0; j < n; ++j)
{
if (i & (1 << j)) // 为1的标示这一行替换固定红包x,求出收益,并标示替换了哪些行
{
ret += row_max - rowSum[j];
rlist[idx++] = j; // 记录高级红包发放行数
}
}
for (int j = 0; j < m; ++j) // 求出替换完行后,每一列如果被替换所得的收益
{
h[j] = col_max - colSum[j];
for (int l = 0; l < idx; ++l)
{
h[j] += money[rlist[l]][j] - x;
}
}
sort(h.begin(), h.end(), cmp); // 根据收益大小排序,得到最大收益的列的顺序
for (int j = 0; j + cnt < k && h[j] > 0; ++j) // k-cnt剩余的就通过替换列来补充,直接加上列的收益即可
{
ret += h[j];
}
ans = max(ans, ret); // 更新最大收益
}
printf("%lld\n", ans);
return 0;
}
相关文章推荐
- 51Nod - 1625 夹克爷发红包(暴力+贪心)
- 51NOD 1625 夹克爷发红包 (贪心+dfs)
- 51nod 1625 夹克爷发红包,暴力+贪心
- 51NOD 1625 夹克爷发红包 枚举+贪心
- 51nod 1625 夹克爷发红包
- 51nod 1625 夹克爷发红包
- 51nod 1625夹克爷发红包(贪心+枚举)
- 51nod 1625 夹克爷发红包(状压枚举+贪心)
- 51nod 1625 夹克爷发红包【思维+暴力+贪心】好题~
- 1625 夹克爷发红包(二进制枚举运用)
- 51 nod 1625 夹克爷发红包【贪心、二进制枚举】
- 1625 夹克爷发红包 51HOD
- 51Nod-1625-夹克爷发红包
- 1625 夹克爷发红包
- 1625 夹克爷发红包 贪心 + 暴力 + 思维
- 51 Nod 1625 夹克爷发红包
- 51nod 1378 夹克老爷的愤怒
- 51Nod-1378-夹克老爷的愤怒
- 51nod 1378:夹克老爷的愤怒
- 51nod 1378 夹克老爷的愤怒(树形dp,贪心)