URAL 1326. Bottle Taps 压缩DP

URAL  1326. Bottle Taps     压缩DP



题目大意,程序猿想收集tags,还差几个没收集到,问最少花费是多少才能收集完!
给定n,  接下来n个tags的单价;
给定m,然后m中成套收集的方式,每套规定价格,还有个数,后面跟着标号;都是唯一的,证明,每种只需要一种!
最后在给出需要收集那几个,每个都是唯一的!

因为n是最大20;  
注意:
可以重复收集,利用压缩DP去做,所谓压缩DP就是利用二进制数表示一种是否已经收集,收集一个或多个用1表示,没有则用0来表示!   第一个没有收集,第二三个已经收集,就用 110即6来表示收集的状态!  其实就是利用或运算的性质来处理!

其他的细节在下面的代码中已经体现了!

#include<iostream>
#include<cstdio>


using namespace std;
struct node
{
    int price,cnt;
}nod[120];
int n,m;
int par[22];
int dp[1<<21];
void DFS(int x,int k,int pri)
{
    if(x==n)
    {
        dp[k]=pri;
        return ;
    }
    DFS(x+1,k,pri);///这件不买
    DFS(x+1,k|(1<<x) ,pri+par[x]);///这件买
}
int main()
{
    cin>>n;
    m=1<<n;
    for(int i=0;i<n;++i)cin>>par[i];
    DFS(0,0,0);///初始化单件购买的情况,没见选择购买或者不购买!
    int k;cin>>k;
    for(int i=0;i<k;++i)
    {
        cin>>nod[i].price;
        int t,tmp;cin>>t;
        while(t--)
        {
            cin>>tmp; tmp--;
            nod[i].cnt=nod[i].cnt|(1<<tmp);
        }
    }


    int w;cin>>w;
    int tar=0;
    while(w--)
    {
        int tmp;cin>>tmp;
        tmp--;
        tar=tar|(1<<tmp);
    }


    int ans=1000*100;


    for(int i=0;i<m;++i)
    {
        if((i&tar)==tar) ans=min(ans,dp[i]);///注意这里是且运算,他的兴致是只要tar中每位是1的位置i都满足是1,那就等于tar;就是说该卖的都买了吗
        for(int j=0;j<k;++j)
        {///想想背包的思想,从小到大可以买多次
            dp[i|nod[j].cnt]=min(dp[i|nod[j].cnt],dp[i]+nod[j].price);
        }


    }
    cout<<ans<<endl;






    return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值