问题是在能够达到至少p能量的要求下,最小花费为多少,若大于50000则输出TAT
分析: 两次多重背包dp 先dp出至少p能量的最小体积 然后从50000花费再dp出体积 在满足之前的最小体积下找到答案
为啥不体积dp出花费呢? - - 看看哪个数量级大就知道了 要选取合适的状态减少复杂度 233
记得二进制优化233
代码:
// // Created by TaoSama on 2015-09-25 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; int n, m, p; int dp[60005]; //1: dp[i][j]:= i desert j energy's minimum size //2: dp[i][j]:= i truck j cost's maximum size int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); int t; scanf("%d", &t); while(t--) { scanf("%d%d%d", &n, &m, &p); memset(dp, 0x3f, sizeof dp); dp[0] = 0; for(int i = 1; i <= n; ++i) { int w, v, c; scanf("%d%d%d", &w, &v, &c); for(int k = 1; c > 0; c -= k, k <<= 1) { int mul = min(k, c); for(int j = p + 100; j >= mul * w; --j) dp[j] = min(dp[j], dp[j - mul * w] + mul * v); } } int V = INF; for(int i = p; i <= p + 100; ++i) V = min(V, dp[i]); // printf("V: %d\n", V); memset(dp, 0, sizeof dp); int ans = INF; for(int i = 1; i <= m; ++i) { int v, w, c; scanf("%d%d%d", &v, &w, &c); for(int k = 1; c > 0; c -= k, k <<= 1) { int mul = min(k, c); for(int j = 50000; j >= mul * w; --j) { dp[j] = max(dp[j], dp[j - mul * w] + mul * v); if(dp[j] >= V) ans = min(ans, j); } } } if(ans == INF) puts("TAT"); else printf("%d\n", ans); } return 0; }
Storage Keepers
题意: 有n<100个仓库 m<=30个管理员 每个管理员有一个能力值P(接下来的一行有m个数,表示每个管理员的能力值)
每个仓库只能由一个管理员看管,但是每个管理员可以看管k个仓库(但是这个仓库分配到的安全值只有p/k,k=0,1,...
每个月公司都要给看管员工资,雇用的管理员的工资即为他们的能力值p和,求使每个仓库的安全值最高的前提下 使的工资总和最小。
输出最大安全值,并且输出最少的花费。
分析: 两次类似于多重背包的dp 状态见代码 第一次dp出安全值 第二次再在这个状态下找到最少花费 注意初始化好好想想啊
代码:
// // Created by TaoSama on 2015-08-12 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; int n, m, p[35]; int f[35][105], g[35][105]; //dp[i][j]:= i people look after j storages max safe, min wage int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); while(scanf("%d%d", &m, &n) == 2 && (n || m)) { for(int i = 1; i <= n; ++i) scanf("%d", p + i); memset(f, 0, sizeof f); f[0][0] = INF; //initialization is so difficult! for(int i = 1; i <= n; ++i) { for(int j = 0; j <= m; ++j) { f[i][j] = f[i - 1][j]; //zero exception for(int k = 1; k <= p[i] && k <= j; ++k) f[i][j] = max(f[i][j], min(f[i - 1][j - k], p[i] / k)); } } int L = f[n][m]; if(!L) {printf("0 0\n"); continue;} memset(g, 0x3f, sizeof g); g[0][0] = 0; for(int i = 1; i <= n; ++i) { for(int j = 0; j <= m; ++j) { g[i][j] = g[i - 1][j]; for(int k = 1; k <= p[i] && k <= j; ++k) { int s = p[i] / k; //at least if(s >= f[n][m]) g[i][j] = min(g[i][j], g[i - 1][j - k] + p[i]); } } } int Y = g[n][m]; printf("%d %d\n", L, Y); } return 0; }
The Fewest Coins
// // // // Created by TaoSama on 2015-03-30 // Copyright (c) 2015 TaoSama. All rights reserved. // #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int N = 1e5 + 10; int n, t, dpp[25000], dpn[15000], c[105], v[105]; int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); cin >> n >> t; for(int i = 1; i <= n; ++i) cin >> v[i]; for(int i = 1; i <= n; ++i) cin >> c[i]; memset(dpp, 0x3f, sizeof dpp); dpp[0] = 0; for(int i = 1; i <= n; ++i) { int k = 1; while(c[i] > 0) { int t = min(c[i], k); for(int j = t + 120 * 120; j >= t * v[i]; --j) dpp[j] = min(dpp[j], dpp[j - t * v[i]] + t); c[i] -= k; k <<= 1; } } /*for(int i = 0; i <= t + 120 * 120; ++i) if(dpp[i] != INF) printf("dpp[%d]: %d\n", i, dpp[i]);*/ memset(dpn, 0x3f, sizeof dpn); dpn[0] = 0; for(int i = 1; i <= n; ++i) for(int j = v[i]; j <= 120 * 120; ++j) dpn[j] = min(dpn[j], dpn[j - v[i]] + 1); /*for(int i = 0; i <= 120 * 120; ++i) if(dpn[i] != INF) printf("dpn[%d]: %d\n", i, dpn[i]);*/ int ans = INF; for(int i = 0; i <= 120 * 120; ++i) ans = min(ans, dpp[t + i] + dpn[i]); if(ans == INF) ans = -1; cout << ans << endl; return 0; }