[hdu5445 Food Problem]多重背包
题意:一堆食物,有价值、空间、数量三种属性,一些卡车,有空间,价格,数量三种属性。求最少的钱(不超过50000)买卡车装下价值大于等于给定价值的食物,食物可以拆开来放。
思路:这题的关键是给定的条件:食物可以拆开来放。这个条件使得卡车和食物可以分开考虑,然后通过空间这个属性联系在一起。做两遍多重背包即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#pragma comment(linker, "/STACK:10240000") #include <bits/stdc++.h> using namespace std; #define X first #define Y second #define pb push_back #define mp make_pair #define all(a) (a).begin(), (a).end() #define fillchar(a, x) memset(a, x, sizeof(a)) typedef long long ll; typedef pair<int, int> pii; namespace Debug { void print(){cout<<endl;}template<typename T> void print(const T t){cout<<t<<endl;}template<typename F,typename...R> void print(const F f,const R...r){cout<<f<<" ";print(r...);}template<typename T> void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;} } template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);} template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} /* -------------------------------------------------------------------------------- */ int dp[60000]; void zeroPack_min(int V, int v, int w) { for (int i = V; i >= v; i --) { umin(dp[i], dp[i - v] + w); } } void zeroPack_max(int V, int v, int w) { for (int i = V; i >= v; i --) { umax(dp[i], dp[i - v] + w); } } void MultiPack(int V, int v, int w, int remain, bool id) { if (!remain) return; int num = 1; while (remain) { if (!id) zeroPack_min(V, v * num, w * num); else zeroPack_max(V, v * num, w * num); remain -= num; num <<= 1; umin(num, remain); } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); #endif // ONLINE_JUDGE int T, n, m, p, v, w, c; cin >> T; while (T --) { cin >> n >> m >> p; fillchar(dp, 0x3f); dp[0] = 0; for (int i = 0; i < n; i ++) { scanf("%d%d%d", &v, &w, &c); MultiPack(p + 100, v, w, c, 0); } int place = 0x3f3f3f3f; for (int i = p; i <= p + 100; i ++) umin(place, dp[i]); fillchar(dp, 0); for (int i = 0; i < m; i ++) { scanf("%d%d%d", &w, &v, &c); MultiPack(50000, v, w, c, 1); } int ans = -1; for (int i = 0; i <= 50000; i ++) { if (dp[i] >= place) { ans = i; break; } } if (~ans) cout << ans << endl; else puts("TAT"); } } |