• 【题解】P1064 [NOIP2006 提高组] 金明的预算方案


    P1064 [NOIP2006 提高组] 金明的预算方案

    与传统01背包不同的是,每个主件不再是只有选/不选两种情况,由于还带有0/1/2个附件,所以每个主件一共有如下种情况:

    没有附件:

    不选主件/选主件(价格允许的话)

    有一个附件:

    不选主件/选主件(价格允许的话)/选主件和附件(价格允许选二者的话)

    有两个附件:

    不选主件/选主件(价格允许的话)/选主件和附件A(价格允许选二者的话)/选主件和附件B(价格允许选二者的话)/选主件和附件A和附件B(价格允许选二者的话)

    这个题的特性是附件的数量少,只有0/1/2个,因此我们可以把附件涵盖在主件内处理而不用单独考虑附件的选择条件。

    坑点:由于附件不单独处理,所以如果开二维数组进行DP每次沿用上一行的状态的话会调用到附件的空状态。所以应该直接开一维数组然后倒序枚举总钱数。

    优化:由于物品价格都是10的倍数所以一开始就把n和v同时除以10最后总答案输出时再乘上10即可。

    int n, m, q;
    struct furniture{
        int v, p, ifmain;
        vi fujian;
    }fur[66];
    ll f[32010];
    int main(){
        n = rd(); m = rd(); n /= 10;
        for(int i = 1; i <= m; ++i){
            fur[i].v = rd(); fur[i].v /= 10;
            fur[i].p = rd();
            q = rd();
            if(q != 0){
                fur[q].fujian.pb(i);
                fur[i].ifmain = 0;
            }
            else fur[i].ifmain = 1;
        }
        for(int i = 1; i <= m; ++i){
            if(!fur[i].ifmain)  continue;
            for(int j = n; j >= 1; --j){
                if(j < fur[i].v)    continue;
                int kind = fur[i].fujian.size();
                if(kind >= 0){
                    f[j] = max(f[j], f[j - fur[i].v] + fur[i].v * fur[i].p);    
                }
                if(kind >= 1){
                    if(j >= fur[i].v + fur[fur[i].fujian[0]].v)    
                        f[j] = max(f[j], f[j - fur[i].v - fur[fur[i].fujian[0]].v] + fur[i].v * fur[i].p + fur[fur[i].fujian[0]].v * fur[fur[i].fujian[0]].p);
                }
                if(kind >= 2){
                    if(j >= fur[i].v + fur[fur[i].fujian[1]].v)
                        f[j] = max(f[j], f[j - fur[i].v - fur[fur[i].fujian[1]].v] + fur[i].v * fur[i].p + fur[fur[i].fujian[1]].v * fur[fur[i].fujian[1]].p);
                    if(j >= fur[i].v + fur[fur[i].fujian[0]].v + fur[fur[i].fujian[1]].v)
                        f[j] = max(f[j], f[j - fur[i].v - fur[fur[i].fujian[0]].v - fur[fur[i].fujian[1]].v] + fur[i].v * fur[i].p + fur[fur[i].fujian[0]].v * fur[fur[i].fujian[0]].p + fur[fur[i].fujian[1]].v * fur[fur[i].fujian[1]].p);
                }
            }
        }
        printf("%lld
    ", f[n] * 10);
    	return 0;
    }
    
  • 相关阅读:
    iOS-深入理解(转载)
    iOS开发
    夜光遥感
    希尔伯特曲线在地图图像分割中的应用
    希尔伯特曲线
    NLP生成论文
    MapGIS SDK(C++)【基础篇】
    从npm到vue和nodejs
    分形在遥感和GIS中的应用
    MapReduce、Hadoop、PostgreSQL、Spark
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/14983669.html
Copyright © 2020-2023  润新知