• UESTC-2016dp专题 F 柱爷与三叉戟不得不说的故事


    柱爷与三叉戟不得不说的故事

    Time Limit: 500/500MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)

    题目链接

    http://acm.uestc.edu.cn/#/contest/show/96

     

    Description

    在喵蛤蛤城,人人都知晓柱爷有一把传奇武器三叉戟.据传,这是一位在772002772002年前陨落的强大守护者F91曾经使用过的12级灵能武器,拥有毁天灭地的力量

    但只有很少人知道当柱爷获得三叉戟时,三叉戟的力量已经消失殆尽.为了能修复三叉戟的力量,柱爷苦心专研古籍,发现只有找到最神秘的1515种元素,将元素的力量重新注入到三叉戟中,三叉戟就能恢复到原来的力量,于是柱爷踏上了寻找神秘元素的旅行.

    柱爷首先发现1515个由卿学姐掌控的地牢,里面正好有1515种对应元素.冷静的柱爷没有贸然行动,经过一番详细的打听,柱爷得知了第ii种元素需要DiDi的精力去获得;与此同时,柱爷还发现了由白学潘看守的NN个洞穴,第ii个洞穴中有AiAi个不同的元素,分别是B1,B2,...,BAiB1,B2,...,BAi,需要CiCi的精力去获得.

    同种元素不得拥有多个,不然元素之间会产生强大的斥力,会发生爆炸;不能攻下一个洞穴后,留有元素不拿走,元素可能会辐射,伤害喵哈哈村的大爷......

    但是柱爷岂是凡人?柱爷修复三叉戟时花费的总是最小的精力!

    那么这个最小的花费是多少呢?

    Input

    第一行包括1515个正整数,第ii个数表示DiDi.

    第二行包括一个整数表示NN.

    接下来NN行,每行有一个整数表示AiAi,后面紧接着AiAi个不同的正整数,最后又一个正整数CiCi表示需要花费的精力.

    数据保证:

    • 0N100000≤N≤10000

    • 1Di200001≤Di≤20000

    • 0Ai50≤Ai≤5

    • 1Ci20000001≤Ci≤2000000

    Output

    输出一个整数ansans:

    表示至少花ansans的精力去修复三叉戟.

    Sample input

    9599 11186 3513 3112 19106 1171 4254 4786 11880 19550 4793 17049 10779 11096 97135
    4 10 1 8 11 1212645
    3 14 9 15 1655560
    3 7 3 14 1161262
    5 13 5 9 2 11 710512
    0 980331

    Sample output

    141587


    题意
    有15种元素,有两个方法可以获得,需要付出相应的代价,且元素不能重复,求最小花费。
    思路
    刚学的压缩状态dp,思想是用二进制来表示状态,1表示这个元素有,0表示这个元素还没有,dp[i]表示状态为i时所需要的最小花费,
    则状态如何转移?
    枚举i的子集:for(int j=i;j;j=(j-1)&i),则状态转移方程就很好写了:dp[i]=min(dp[i],dp[j]+dp[j^i]);
    这样就完了。
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn = 1000000;
    const long long int inf = 1e17+7;
    long long int dp[maxn];
    int main()
    {
        int n=15,m;
        for(int i=1;i<maxn;i++) dp[i]=inf;  //初始化
        for(int i=1;i<=n;i++){
            scanf("%lld",&dp[1<<(i-1)]);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int k,num=0;
            scanf("%d",&k);
            for(int j=1;j<=k;j++){
                int tmp;
                scanf("%d",&tmp);
                num+=(1<<(tmp-1));
            }
            long long int tmp;
            scanf("%lld",&tmp);
            if(dp[num]>tmp)
                dp[num]=tmp;
        }
        for(int i=1;i<(1<<n);i++){
            for(int j=i;j;j=(j-1)&i)
                dp[i]=min(dp[i],dp[j]+dp[j^i]);
        }
        cout<<dp[(1<<n)-1];
        return 0;
    }

     




  • 相关阅读:
    [Windows]使用nmake命令
    正则表达式
    随机读取数据库
    常用正规表达式应用(收集于网络)
    javascript中使用正则表达式(替换应用)
    摘自网络"浅析UpdatePanel的partial render原理"
    css样式制作相册例子(摘自网络)
    javascript正则表达式常规用法(摘自网络)
    asp.net下的正规表达式替换
    摘自网络创业失败的10个教训(上)
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5491684.html
Copyright © 2020-2023  润新知