[hihocoder-1974] 智能分包 状态压缩dp
作者:互联网
题目链接:https://hihocoder.com/problemset/problem/1974
题目:
小Hi在一家电商公司工作,开发订单的智能分包功能。
用户的一个订单可能包含N种不同的商品,其中第i种购买了Ai件。电商公司一共有M个仓库,用户订单中的第i种商品在第k个仓库中的库存是cnt[k][i]件。
有的时候单一仓库的库存不能满足用户的订单需求,这时候就需要将订单分包。比如第1种商品和第2种商品从仓库1发出,第3种商品从仓库3发出……
特别注意订单中的同一种商品只能从单一仓库发出,也就是说不应该出现类似用户买了3瓶可乐,结果2瓶从一个仓库发出,1瓶从另一个仓库发出的情况。
请你帮小Hi实现这个功能,给定用户订单和库存,计算最少从几个不同的仓库发包。如果所有仓库一起都不能满足用户订单,输出-1。
1 <= N <= 20 1 <= M <= 50
题解:状态压缩dp
二进制状态,每一位表示一种产品当前 1有了,0没有。共有(1<<N)-1 种状态
每个仓库提前处理一下变为一个状态整数have,如果c[k][i]>=a[i](能满足客户要求),则hve的第i位为1
循环状态和仓库 ,转移方程: dp[ i | a [ j ] ]=min( dp[ i | a[ j ] ] , dp[ i ]+1 )
1 #include <bits/stdc++.h> 2 using namespace std; 3 int const maxn=1<<21; 4 int n,a[25],m,have[55],dp[maxn]; 5 bool vis[25]; 6 void work(){ 7 for(int i=0;i<n;i++)if(!vis[i]){ 8 printf("-1\n");return ; 9 } 10 int zm=(1<<n)-1; 11 for(int i=1;i<=zm;i++)dp[i]=100; 12 dp[0]=0; 13 for(int i=0;i<=zm;i++) 14 for(int j=1;j<=m;j++){ 15 dp[i|have[j]]=min(dp[i|have[j]],dp[i]+1); 16 } 17 printf("%d\n",dp[zm]); 18 } 19 int main(){ 20 scanf("%d%d",&n,&m); 21 for(int i=0;i<n;i++)scanf("%d",&a[i]); 22 int num; 23 // cout<<maxn<<"haha"<<endl; 24 for(int i=1;i<=m;i++){ 25 have[i]=0; 26 for(int j=0;j<n;j++){ 27 scanf("%d",&num); 28 if(num>=a[j])have[i]=(have[i]<<1)+1,vis[j]=true; 29 else have[i]=have[i]<<1; 30 } 31 } 32 work(); 33 return 0; 34 }
标签:发出,商品,仓库,1974,hihocoder,订单,分包,dp 来源: https://www.cnblogs.com/conver/p/11291123.html