UVA 10003 Cutting Sticks
2012-12-18 17:04
435 查看
大意:确定切割木棍的次序, 代价为当前木棍长度,使得切割的总的代价最小。
思路:我想了很久,后来发现状态转移方程可以这样表示:d[i][j] = min(d[i][j], d[i][k]+d[k][j]+(a[j]-a[i])) (i<=k< j)
d[i][j]数组表示在区间[i,j]内切割木棍的最小代价,这样问题及其子问题都具有最优结构,无后效性,这样我们只要确定状态变量以及当前决策就可以表示出状态转移方程,最大代价类似。
注意一些细节,当i == j时,d[i][j] = 0,而我们求min(d[i][j])时,须把d[i][j]赋值为INF,如果求得的d[i][j]仍为INF,则赋值为0,我的理解是可能在区间[i,j]之间可能不存在a[i],所以d[i][j]必须为0,表示没有切割。
于是可以用两种方法实现,第一种类似矩阵链乘,第二种为记忆化搜索。
思路:我想了很久,后来发现状态转移方程可以这样表示:d[i][j] = min(d[i][j], d[i][k]+d[k][j]+(a[j]-a[i])) (i<=k< j)
d[i][j]数组表示在区间[i,j]内切割木棍的最小代价,这样问题及其子问题都具有最优结构,无后效性,这样我们只要确定状态变量以及当前决策就可以表示出状态转移方程,最大代价类似。
注意一些细节,当i == j时,d[i][j] = 0,而我们求min(d[i][j])时,须把d[i][j]赋值为INF,如果求得的d[i][j]仍为INF,则赋值为0,我的理解是可能在区间[i,j]之间可能不存在a[i],所以d[i][j]必须为0,表示没有切割。
于是可以用两种方法实现,第一种类似矩阵链乘,第二种为记忆化搜索。
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> using namespace std; const int INF = 0x3f3f3f3f; int d[51][51]; int a[51]; int L, n; void init() { memset(d, 0, sizeof(d)); } int read_case() { scanf("%d", &L); if(!L) return 0; scanf("%d", &n); a[0] = 0, a[n+1] = L; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); return 1; } int dp() { init(); for(int r = 1; r <= n+1; r++) //划分阶段 { for(int i = 0; i <= n-r+1; i++) //j-i = r, j <= n+1 -> i <= n-r+1; { int j = i+r; // j-i = r -> j = i+r; d[i][j] = INF; for(int k = i+1; k < j; k++) { int t = d[i][k]+d[k][j]+a[j]-a[i]; d[i][j] = min(d[i][j], t); } if(d[i][j] == INF) d[i][j] = 0; } } return d[0][n+1]; } void solve() { int ans = dp(); printf("The minimum cutting is %d.\n", ans); } int main() { while(read_case()) { solve(); } return 0; }
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> using namespace std; const int INF = 0x3f3f3f3f; int d[51][51]; int a[51]; int n, L; bool vis[51][51]; void init() { memset(d, 0, sizeof(d)); memset(vis, 0, sizeof(vis)); } int dp(int i, int j) { int &ans = d[i][j]; if(vis[i][j]) return ans; vis[i][j] = 1; ans = INF; for(int r = i+1; r < j; r++) { ans = min(ans, dp(i, r) + dp(r, j) + (a[j]-a[i])); } if(ans == INF) ans = 0; return ans; } int read_case() { init(); scanf("%d", &L); if(!L) return 0; scanf("%d", &n); a[0] = 0, a[n+1] = L; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); return 1; } void solve() { int ans = dp(0, n+1); printf("The minimum cutting is %d.\n", ans); } int main() { while(read_case()) { solve(); } return 0; }
相关文章推荐
- UVA 10003 Cutting Sticks(区间 DP)
- uva 10003 Cutting Sticks 切木条dp
- UVA 10003 Cutting Sticks(切棍子)
- 【DP】UVA 10003 Cutting Sticks 类似矩阵链乘
- uva10003 Cutting Sticks
- uva 10003——Cutting Sticks
- UVa 10003 Cutting Sticks
- UVa #10003 Cutting Sticks (例题9-9)
- uva 10003 Cutting Sticks
- UVA 10003 Cutting sticks
- UVA - 10003 - Cutting Sticks
- UVA 10003 - Cutting Sticks
- UVA-10003 Cutting Sticks (区间DP)
- uva 10003 Cutting Sticks 简单区间dp
- 【DP】UVA 10003 Cutting Sticks 类似矩阵链乘
- 【解题报告】uva10003_Cutting Sticks(切割木棍, dp)
- uva 10003 Cutting Sticks
- 【UVa 10003】【区间DP】Cutting Sticks【有一个长为L的木棍,木棍中间有n个切点。每次切割的费用为当前木棍的长度。求切割木棍的最小费用。】
- UVa 10003 - Cutting Sticks(区间DP+记忆化)
- uva 10003 - Cutting Sticks(区间DP)