動態規劃練習——UVa10003——區間dp
阿新 • • 發佈:2018-11-09
題目連結:https://vjudge.net/contest/232313#problem/I
紫書上的動態規劃例題,很明顯是一個區間線性規劃的問題,想起之前做過的矩陣鏈乘,這題和它很像,列舉方向都是向j-i遞增的
方向,這裡有個大神的區間dp模板的總結:http://www.cnblogs.com/zsboy/archive/2013/03/08/2950261.html,可以強化理解。
所以,設dp[i][j]為切割小木棍i~j點的費用,則dp[i][j]=min{dp[i][k]+dp[k][j]+a[j]-a[i]},a[j]-a[i]表示第一刀切割為i~j的費用,而
dp[i][k]和dp[k][j]就像最優矩陣鏈乘一樣,將問題分割為了兩個子問題,所以長區間必須由短區間推得,和紫書上的思路一樣。
程式碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int maxn=55; int a[maxn]; int dp[maxn][maxn]; const int INF=0x3f3f3f3f; int main() { int l; while(scanf("%d",&l)!=EOF) { if(l==0)break; int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } a[0]=0; a[n+1]=l; for(int i=0;i<=n+1;i++) dp[i][i+1]=0; for(int x=1;x<=n+1;x++)//區間長度 { for(int i=0;i<=n+1;i++)//起點 { int j=i+x;//終點 if(j>n+1)break; int minn=INF; for(int k=i+1;k<j;k++) { int temp=dp[i][k]+dp[k][j]+a[j]-a[i]; minn=min(minn,temp); } if(minn!=INF) dp[i][j]=minn; } } printf("The minimum cutting is %d.\n",dp[0][n+1]); } return 0; }