其中最后一项a[j]-a[i]代表第一刀的费用。切完后,木棍变为i~k和k~j两个部分,状态转移方程由此可得。
记忆化搜索
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1010; const int INF = 0x3f3f3f3f; int c[N] ,dp[N][N]; int len , n; int d(int l, int r) { if(r - l == 1) { return 0; } if(dp[l][r] > 0) { return dp[l][r]; //算过>0,就不要重新再算了 } dp[l][r] = INF; for(int i = l; i <= r; i++) { dp[l][r] = min( dp[l][r], d(l,i)+d(i,r)+c[r] - c[l]); } return dp[l][r]; } int main() { while(scanf("%d",&len) != EOF && len) { scanf("%d",&n); for(int i = 1; i <= n; i++) { scanf("%d",&c[i]); } c[0] = 0; c[n+1] = len; memset(dp,0,sizeof(dp)); int ans = d(0, n+1); printf("The minimum cutting is %d.\n",ans); } return 0; }
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1050; const int INF = 0x3f3f3f3f; int dp[N][N]; int c[N]; int main() { int len, n; while( scanf("%d",&len) != EOF && len) { scanf("%d",&n); for(int i = 1; i <= n; i++) { scanf("%d",&c[i]); } c[0] = 0; c[n+1] = len; memset(dp,0,sizeof(dp)); for(int p = 1; p <= n+1; p++) { //枚举区间的长度为 1 ~ n+1 for(int i = 0; i <= n+1; i++) { //枚举区间的起点为0 ~ n+1 int j = i+p; int mina = INF; for(int k = i+1; k < j; k++) { //枚举断点 mina = min(mina, dp[i][k]+dp[k][j]); } if(mina != INF) { dp[i][j] = mina + c[j]-c[i]; } } } printf("The minimum cutting is %d.\n",dp[0][n+1]); } return 0; }