poj1170(状态压缩dp)

链接:点击打开链接

题意:给定一个含有n种商品的订单,给出订单内每个物品的初始价格和需要购买的数量,再给出m种套餐,这些组合会得到便宜的价格,最后怎样搭配使得总价格最少。

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int dp[500005],HASH[1005];
int SIX[10]={1,6,36,216,1296,7776,46656,279936};
struct node{
    int has,num,val;
}s[205];
int main(){                                     //因为最多有五种物品,因此
    int b,k,m,x,y,i,j,ans,tmp,NUM;              //将每种物品和套餐用六进制
    while(scanf("%d",&b)!=EOF){                 //进行状态压缩
        ans=NUM=0;
        memset(HASH,-1,sizeof(HASH));
        for(i=0;i<b;i++){
            scanf("%d%d%d",&tmp,&s[i].num,&s[i].val);
            s[i].has=SIX[i];
            HASH[tmp]=SIX[i];
            ans+=s[i].num*s[i].val;
            NUM+=SIX[i]*s[i].num;               //将六进制总数作为背包容量
            s[i].num=SIX[i];                    //将每个物品的重量变为六进制
        }                                       //所表示的数
        scanf("%d",&m);
        for(i=0;i<m;i++){
            scanf("%d",&k);
            while(k--){
            scanf("%d%d",&x,&y);
            if(HASH[x]==-1)
            continue;
            s[i+b].num+=HASH[x]*y;              //将套餐变为六进制数
            }
            scanf("%d",&s[i+b].val);
        }
        memset(dp,INF,sizeof(dp));
        dp[0]=0;
        for(i=0;i<b+m;i++)
        for(j=s[i].num;j<=NUM;j++)              //直接转换成完全背包
        dp[j]=min(dp[j],dp[j-s[i].num]+s[i].val);
        printf("%d\n",min(ans,dp[NUM]));
    }
    return 0;
}


 

你可能感兴趣的:(poj1170(状态压缩dp))