DFS(剪枝) - Lead of Wisdom - HDU 6772

DFS(剪枝) - Lead of Wisdom - HDU 6772

2020 Multi-University Training Contest 2 1010

题意:

T 组 测 试 数 据 。 T组测试数据。 T

给 定 n 件 物 品 , 共 有 k 种 , 每 件 物 品 有 四 种 属 性 a i , b i , c i , d i , 给定n件物品,共有k种,每件物品有四种属性a_i,b_i,c_i,d_i, nkai,bi,ci,di

要 从 k 种 物 品 种 , 每 种 物 品 选 择 一 件 , 要从k种物品种,每种物品选择一件, k

使 得 收 益 : 使得收益: 使

D M G = ( 100 + ∑ i ∈ S a i ) ( 100 + ∑ i ∈ S b i ) ( 100 + ∑ i ∈ S c i ) ( 100 + ∑ i ∈ S d i ) DMG=(100+∑_{i∈S}a_i)(100+∑_{i∈S}b_i)(100+∑_{i∈S}c_i)(100+∑_{i∈S}d_i) DMG=(100+iSai)(100+iSbi)(100+iSci)(100+iSdi)

最 大 , 输 出 最 大 收 益 。 最大,输出最大收益。

输入:

首 行 包 括 一 个 正 整 数 T , 表 示 T 组 测 试 数 据 首行包括一个正整数T,表示T组测试数据 TT

每 组 数 据 首 行 包 括 两 个 正 整 数 n , k , 每组数据首行包括两个正整数n,k, n,k

接 着 n 行 数 据 , 每 行 包 括 t i , a i , b i , c i , d i , 分 别 表 示 物 品 种 类 和 物 品 的 四 个 属 性 。 接着n行数据,每行包括t_i,a_i,b_i,c_i,d_i,分别表示物品种类和物品的四个属性。 nti,ai,bi,ci,di

Sample Input

1
6 4
1 17 25 10 0
2 0 0 25 14
4 17 0 21 0
1 5 22 0 10
2 0 16 20 0
4 37 0 0 0

Sample Output

297882000

数据范围:

1 ≤ T ≤ 10 , 1 ≤ n , k ≤ 50 , 1 ≤ t i ≤ k , 0 ≤ a i , b i , c i , d i ≤ 100 1≤T≤10,1≤n,k≤50,1≤t_i≤k,0≤a_i,b_i,c_i,d_i≤100 1T101n,k501tik0ai,bi,ci,di100


分析:

记 第 i 种 装 备 的 数 量 为 c n t i , 记第i种装备的数量为cnt_i, icnti

若 c n t i > 0 , 那 么 选 择 该 物 品 一 定 优 于 不 选 择 该 物 品 。 若cnt_i>0,那么选择该物品一定优于不选择该物品。 cnti>0

故 总 方 案 数 为 ∏ i = 1 k m a x ( c n t i , 1 ) , 其 中 ∑ i = 1 k c n t i ≤ 50 , 故总方案数为\prod_{i=1}^kmax(cnt_i,1),其中\sum_{i=1}^kcnt_i≤50, i=1kmax(cnti,1)i=1kcnti50

最 坏 情 况 为 所 有 c n t i 均 相 等 时 , ∏ i = 1 k m a x ( c n t i , 1 ) 取 最 值 , 最坏情况为所有cnt_i均相等时,\prod_{i=1}^kmax(cnt_i,1)取最值, cntii=1kmax(cnti,1)

假 设 它 们 都 等 于 x , 则 方 案 总 数 为 x n x , 当 x 取 3 时 , 最 大 值 为 3 n 3 , 假设它们都等于x,则方案总数为x^{\frac{n}{x}},当x取3时,最大值为3^{\frac{n}{3}}, xxxnx333n

当 n = 50 时 , 大 约 在 1 0 8 级 别 , 仍 然 是 可 行 的 计 算 量 。 因 此 , 可 以 考 虑 爆 搜 。 当n=50时,大约在10^8级别,仍然是可行的计算量。因此,可以考虑爆搜。 n=50108

注意!!!:

对 于 数 量 为 0 的 某 种 物 品 , 应 当 直 接 跳 过 , 不 能 进 入 搜 索 , 对于数量为0的某种物品,应当直接跳过,不能进入搜索, 0

假 设 第 i 种 物 品 数 量 为 0 , 那 么 当 我 们 枚 举 第 i − 1 种 物 品 时 , 就 会 搜 索 出 c n t i − 1 个 空 节 点 , 假设第i种物品数量为0,那么当我们枚举第i-1种物品时,就会搜索出cnt_{i-1}个空节点, i0i1cnti1

代码:

#include<iostream>
#include<cstring>

#define ll long long

using namespace std;

const int N=55;

int T,n,k;
int cnt[N];
ll ans;
int ne[N];
struct node
{
    int a,b,c,d;
}w[N][N];

void dfs(int u,int a,int b,int c,int d)  
{
    if(u>k)
    {
        ll res=(ll )a*b*c*d;
        ans=max(ans,res);
        return ;
    }
    if(!cnt[u]) 
    {
        dfs(ne[u],a,b,c,d);
        return ;
    }

    for(int i=1;i<=cnt[u];i++)
        dfs(u+1,a+w[u][i].a,b+w[u][i].b,c+w[u][i].c,d+w[u][i].d);
}

int main()
{
    cin>>T;
    while(T--)
    {
        memset(cnt,0,sizeof cnt);
        memset(ne,0,sizeof ne);
        ans=0;
        
        cin>>n>>k;
        for(int i=1;i<=n;i++) 
        {
            int t;
            cin>>t;
            cnt[t]++;
            cin>>w[t][cnt[t]].a>>w[t][cnt[t]].b>>w[t][cnt[t]].c>>w[t][cnt[t]].d;
        }
        
        int last=k+1;
        for(int i=k;i;i--)
        {
            ne[i]=last;
            if(cnt[i]) last=i;
        }

        dfs(1,100,100,100,100);
            
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值