UVA10163 Storage Keepers (动态规划)
$dp[i][j]$表示前$i$个仓库由前$j$个人来守卫能取得的最大安全值;
$cost[i][j]$表示前$i$个仓库由前$j$个人来守护在能取得的最大安全值的情况下的最小花费。
AC代码
//#define LOCAL #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f const int maxn = 100 + 5; const int maxm = 30 + 5; int a[maxm]; int dp[maxn][maxm], cost[maxn][maxm]; void solve(int n, int m) { // init memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { // not choose j dp[i][j] = dp[i][j-1]; // choose j for(int k = 1; k <= i; k++) { int x; if(k == i) x = a[j] / k; else x = min(a[j] / k, dp[i-k][j-1]); if(x > dp[i][j]) { dp[i][j] = x; } } } } memset(cost, INF, sizeof(cost)); memset(cost[0], 0, sizeof(cost[0])); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { cost[i][j] = cost[i][j-1]; for(int k = 1; k <= i; k++) { int safe = a[j] / k; if(safe >= dp[n][m]) { cost[i][j] = min(cost[i][j], cost[i-k][j-1] + a[j]); } } } } } int main() { #ifdef LOCAL freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); #endif int n, m; while(scanf("%d%d", &n, &m) == 2 && n && m) { for(int i = 1; i <= m; i++) { scanf("%d", &a[i]); } solve(n, m); printf("%d %d\n", dp[n][m], dp[n][m]==0?0:cost[n][m]); } return 0; }
如有不当之处欢迎指出!