51nod1625 夹克爷发红包(贪心+dfs)

Posted xiongtao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1625 夹克爷发红包(贪心+dfs)相关的知识,希望对你有一定的参考价值。

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1625

在公司年会上,做为互联网巨头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

题目意思就是,一个n*m的矩阵的人,每个人都有一个普通的红包,现在有一种x元的高级红包,有k次机会发高级红包,
只能一行或一列发,并且得到高级红包的人将没收普通红包。问最多可以发出去多少红包总金额。(给的样例也是醉了,
居然有高级红包还没有普通红包多的)
题目思路:有dfs搜索每行要高级红包或者不要的所以情况,在解决列变化的情况。
代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
ll ans,n,m,x,k;
ll a[15][250],b[15][250],vis[250],all[250];

void solve()
{
    ll used=0;//已经使用了几次高级红包 
    for(int i=0;i<n;i++)
        if(vis[i])
            used++;
    for(int i=0;i<n;i++)//记录变化每个人金钱数 
        for(int j=0;j<m;j++) 
            if(vis[i])//是高级红包就要改变原来的值 
                b[i][j]=x;
            else
                b[i][j]=a[i][j];
    ll sum=0;//记录全部总金钱数 
    memset(all,0,sizeof(all));//all记录改变后,每列总金钱数 
    for(int j=0;j<m;j++)
    { 
        for(int i=0;i<n;i++) 
        {
            all[j]+=b[i][j]; 
            sum+=b[i][j];
        }
    }
    int kk=k-used;//剩下的使用高级红包的次数 
    sort(all,all+m);//排序,用来查找列金额是否有小于使用高级红包的 
    for(int i=0;i<m;i++)
    {
        if(all[i]<n*x&&kk>0)//可以对此时的i列用高级红包 
        {
            sum-=all[i];
            sum+=n*x;
            kk--;
        }
    }
    ans=max(ans,sum);//记录最大值 
}

void dfs(int h,int sum)
{
    if(sum>k)//超过k次 
        return ;
    if(h==n)//行数都考虑完了 
        solve();
    else
    {
        vis[h]=1;//当前h行要高级红包 
        dfs(h+1,sum+1);
        vis[h]=0;//不要高级红包 
        dfs(h+1,sum);
    }
}
int main()
{
    scanf("%lld%lld%lld%lld",&n,&m,&x,&k);
    memset(vis,0,sizeof(vis));
    ans=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            scanf("%lld",&a[i][j]);
    dfs(0,0);
    printf("%lld
",ans);
    return 0;
}

 










以上是关于51nod1625 夹克爷发红包(贪心+dfs)的主要内容,如果未能解决你的问题,请参考以下文章

51nod1380 夹克老爷的逢三抽一

51Nod 1378 夹克老爷的愤怒

51Nod 1380 夹克老爷的逢三抽一

[51nod] 1378 夹克老爷的愤怒 #树形DP

51nod 1380 夹克老爷的逢三抽一 堆 脑洞题

51Nod1053 最大M子段和V2 二分+DP