星夜行 2018-05-05
$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; }
如有不当之处欢迎指出!
动态规划有时被称为递归的相反的技术。动态规划方案通常使用一个数组来建立一张表,用于存放被分解成众多子问题的解。当算法执行完毕,最终的解法将会在这个表中找到。今天我们先从我们最熟的斐波那契数列数列开始。
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio&am