大体题意:
给你一个长度为L 的木棍,木棍上有n(n <= 50)个结点,切一刀的费用为当前木棍的长度值,问最后把这n个结点全部切掉的话,最小费用是多少!
大不看下面的思路,自己又重新思考了一遍 2016.10.9 21:19
这就是最优三角剖分或者叫 最优矩阵链乘!
直接记忆化搜索即可! 枚举切得中间哪一刀即可!然后分成两部分去dfs!在加上权值(棍子长度即可!)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 50 + 10;
int a[maxn];
int dp[maxn][maxn];
int dfs(int l,int r){
int& ans = dp[l][r];
if (ans != -1)return ans;
if (l > r){
return ans = 0;
}
if (l == r){
return ans = a[r+1] - a[l-1];
}
ans = 0x3f3f3f3f;
for (int k = l; k <= r; ++k){
ans = min(ans,dfs(l,k-1) + dfs(k+1,r) + (-a[l-1]) + a[r+1]);
// printf("ans = %d\n",ans);
}
return ans;
}
int main(){
int L;
while(scanf("%d",&L) == 1 && L){
int n;
scanf("%d",&n);
memset(dp,-1,sizeof dp);
for (int i = 1; i <= n; ++i){
scanf("%d",&a[i]);
}
a[0] = 0;
a[n+1] = L;
printf("The minimum cutting is %d.\n",dfs(1,n));
}
return 0;
}
====================================
思路:
用a[i] 记录第i 个结点的位置!
并把a[0] = 0,a[n+1] = L,这样做就可以处理边界情况了!
写个dp(i,j)函数记忆话搜索!
因为i j 之间必须有东西才可以处理嘛,所以直接判断i >= j-1的话,直接return 0;
因为是记忆话搜索 所以 如果d[i][j]如果不为-1的话 直接return d [i][j]
否则遍历i,j之间的东西!
转移方程为:
dp(i,k) + dp(k,j) + a[j] - a[i];
更新d[i][j]即可!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int l,n;
const int maxn = 50 + 5;
int d[maxn][maxn],a[maxn];
int dp(int i,int j){
if (i >= j-1)return 0;
if (d[i][j] >= 0)return d[i][j];
for (int k = i + 1; k < j; ++k){
int u = dp(i,k) + dp(k,j) + a[j] - a[i];
if (u < d[i][j] || d[i][j] == -1)d[i][j] = u;
}
return d[i][j];
}
int main(){
while(scanf("%d",&l) == 1 && l) {
scanf("%d",&n);
for (int i = 1; i <= n; ++i)scanf("%d",&a[i]);
a[0] = 0;
a[n+1] = l;
memset(d,-1,sizeof d);
printf("The minimum cutting is %d.\n",dp(0,n+1));
}
return 0;
}