URAL 1326. Bottle Taps 压缩DP

来源:互联网 发布:做淘宝客服流程 编辑:程序博客网 时间:2024/06/05 16:42

URAL  1326. Bottle Taps     压缩DP



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

状态压缩:http://godfrey90.iteye.com/blog/725562
因为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;}


原创粉丝点击