考察:背包dp
思路:
做之前看成01背包,然后答案一直不对,醉了.
实际是完全背包,因为需要的东西不超过5类,且不超过5个,所以可以用5维数组.5类物品的数目都是体积.
需要将编号离散化,这里用的是map映射.
但是注意的是我的本地IDE 在mp[x] = mp.size()是从1开始,但是洛谷的IDE是从0开始.可能不同编辑器不一样,还是老老实实设置一个变量较好.
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <map> 5 #include <vector> 6 using namespace std; 7 const int N = 105,M = 6,INF = 0x3f3f3f3f; 8 typedef pair<int,int> PII; 9 vector<PII> dis[N]; 10 map<int,int> mp; 11 int s,n,price[N],f[M][M][M][M][M],cnt; 12 int need[M]; 13 struct LIST{ 14 int nums[6],pce; 15 }list[N+M]; 16 int get(int x) 17 { 18 if(!mp.count(x)) mp[x] =mp.size(); 19 return mp[x]; 20 } 21 void init() 22 { 23 scanf("%d",&s); 24 for(int i=1;i<=s;i++)//折扣 25 { 26 int m,c,k; 27 scanf("%d",&m); 28 for(int j=1;j<=m;j++) 29 { 30 scanf("%d%d",&c,&k); 31 dis[i].push_back({c,k}); 32 } 33 scanf("%d",&price[i]); 34 } 35 scanf("%d",&n); 36 for(int i=1;i<=n;i++)//需求 37 { 38 int c,k,p; scanf("%d%d%d",&c,&k,&p); 39 list[++cnt].nums[get(c)] = 1; 40 list[cnt].pce = p; 41 need[get(c)] = k; 42 } 43 cnt++; 44 for(int i=1;i<=s;i++,cnt++) 45 for(int j=0;j<dis[i].size();j++) 46 { 47 int x = get(dis[i][j].first),y = dis[i][j].second; 48 if(x>5) continue; 49 list[cnt].nums[x] = y; 50 list[cnt].pce = price[i]; 51 } 52 } 53 void work() 54 { 55 memset(f,0x3f,sizeof f); 56 f[0][0][0][0][0] = 0; 57 for(int I=1;I<=cnt;I++) 58 for(int i=list[I].nums[1];i<=need[1];i++) 59 for(int j=list[I].nums[2];j<=need[2];j++) 60 for(int k=list[I].nums[3];k<=need[3];k++) 61 for(int p=list[I].nums[4];p<=need[4];p++) 62 for(int l=list[I].nums[5];l<=need[5];l++) 63 { 64 int a = list[I].nums[1],b = list[I].nums[2]; 65 int c = list[I].nums[3],d = list[I].nums[4]; 66 int e = list[I].nums[5],g = f[i][j][k][p][l]; 67 if(f[i-a][j-b][k-c][p-d][l-e]>=INF) continue; 68 f[i][j][k][p][l] = min(f[i-a][j-b][k-c][p-d][l-e]+list[I].pce,g); 69 } 70 71 } 72 int main() 73 { 74 init(); 75 work(); 76 printf("%d\n",f[need[1]][need[2]][need[3]][need[4]][need[5]]); 77 return 0; 78 }