Shopping Offers USACO 3.3 (dp完全背包)
这题能做对我都不信,开始想了好久感觉确实类似完全背包,dp表不好定义,完全背包一维数组就完了,这里最多要买5种商品
于是去看了眼题解,就看到dp两字和一个5维数组....
我去,真有5维数组这种东西...不过一想确实可以啊,虽然麻烦点。不过一样是完全背包的思想。
dp[5][5][5][5][5],有点区别是完全背包原题是求最大价值,
状态方程是dp[n]=max(dp[n],dp[n-weight(m)]+value(m));且初始dp[1]到dp[n]为0
这里要求最小,就要反过来一下
初始时dp[a][b][c][d][e] (a-e分别代表对应位置的商品的个数)要=a*price(1)+b*price(2)... ,就是单独买的价格(此时肯定是价格最高的)
然后状态方程是
dp[a][b][c][d][e]=min(dp[a][b][c][d][e],dp[a-优惠对应位置商品的数量][...]+优惠的价格)
当然前提是 优惠的商品数量一定小于等于对应的a-e
最后结果存储在dp[][][][][] 要买的数量里...
第二次就过了哈哈哈、
1 /* 2 3 ID: hubiao cave 4 5 PROG: shopping 6 7 LANG: C++ 8 9 */ 10 11 12 13 14 #include<iostream> 15 #include<fstream> 16 #include<utility> 17 #include<list> 18 #include<algorithm> 19 #include<cstring> 20 21 using namespace std; 22 23 24 struct offer 25 { 26 pair<int,int> kind_and_number[5]; 27 int price; 28 int goods_number; 29 }; 30 31 list<offer*> g_offer_list; 32 33 int g_customers[1000][2]; 34 int g_offer_number; 35 int g_buy_number; 36 pair<int,int> g_kind_number[5]; 37 38 int dp[6][6][6][6][6]={0}; 39 40 int main() 41 42 { 43 44 ifstream fin("shopping.in"); 45 ofstream fout("shopping.out"); 46 fin>>g_offer_number; 47 for(int i=0;i<g_offer_number;i++) 48 { 49 offer*po=new offer; 50 memset(po,0,sizeof(offer)); 51 fin>>po->goods_number; 52 for(int j=0;j<po->goods_number;j++) 53 fin>>po->kind_and_number[j].first>>po->kind_and_number[j].second; 54 fin>>po->price; 55 g_offer_list.push_back(po); 56 } 57 58 fin>>g_buy_number; 59 for(int i=0;i<g_buy_number;i++) 60 { 61 int temp; 62 fin>>temp; 63 fin>>g_customers[temp][0]>>g_customers[temp][1]; 64 g_kind_number[i].first=temp; 65 g_kind_number[i].second=g_customers[temp][0]; 66 } 67 68 for(list<offer*>::iterator it=g_offer_list.begin();it!=g_offer_list.end();) 69 { 70 bool flag=false; 71 for(int i=0;i<(*it)->goods_number;i++) 72 { 73 int kind=(*it)->kind_and_number[i].first; 74 int number=(*it)->kind_and_number[i].second; 75 if(!g_customers[kind][0]||g_customers[kind][0]<number) 76 { 77 it=g_offer_list.erase(it); 78 flag=true; 79 continue; 80 } 81 } 82 if(!flag) 83 { 84 it++; 85 //sort(it->kind_and_number[0],it->kind_and_number[it->goods_number]); 86 } 87 88 } 89 90 91 sort(&g_kind_number[0],&g_kind_number[g_buy_number]); 92 for(list<offer*>::iterator it=g_offer_list.begin();it!=g_offer_list.end();it++) 93 { 94 95 for(int i=0;i<5;i++) 96 { 97 for(int j=0;j<5;j++) 98 { 99 if((*it)->kind_and_number[j].first==g_kind_number[i].first) 100 { 101 if(i==j) 102 break; 103 else 104 { 105 swap((*it)->kind_and_number[i],(*it)->kind_and_number[j]); 106 break; 107 } 108 } 109 } 110 } 111 } 112 113 for(int a=0;a<=g_kind_number[0].second;a++) 114 for(int b=0;b<=g_kind_number[1].second;b++) 115 for(int c=0;c<=g_kind_number[2].second;c++) 116 for(int d=0;d<=g_kind_number[3].second;d++) 117 for(int e=0;e<=g_kind_number[4].second;e++) 118 { 119 pair<int,int>*p=g_kind_number; 120 dp[a][b][c][d][e]=a*g_customers[p[0].first][1]+b*g_customers[p[1].first][1]+c*g_customers[p[2].first][1]+d*g_customers[p[3].first][1]+e*g_customers[p[4].first][1]; 121 } 122 123 for(list<offer*>::iterator it=g_offer_list.begin();it!=g_offer_list.end();it++) 124 { 125 126 for(int a=0;a<=g_kind_number[0].second;a++) 127 for(int b=0;b<=g_kind_number[1].second;b++) 128 for(int c=0;c<=g_kind_number[2].second;c++) 129 for(int d=0;d<=g_kind_number[3].second;d++) 130 for(int e=0;e<=g_kind_number[4].second;e++) 131 { 132 pair<int,int>* p=(*it)->kind_and_number; 133 int price=(*it)->price; 134 if(p[0].second<=a&&p[1].second<=b&&p[2].second<=c&&p[3].second<=d&&p[4].second<=e) 135 { 136 dp[a][b][c][d][e]=min(dp[a][b][c][d][e],dp[a-p[0].second][b-p[1].second][c-p[2].second][d-p[3].second][e-p[4].second]+price); 137 } 138 } 139 } 140 141 fout<<dp[g_kind_number[0].second][g_kind_number[1].second][g_kind_number[2].second][g_kind_number[3].second][g_kind_number[4].second]<<endl; 142 143 return 0; 144 145 146 }