poj1651 Multiplication Puzzle 区间DP
题目链接:http://poj.org/problem?id=1651
区间DP思想:
定义dp[i][j]表示区间(i,j)删除其中的所有元素后(当然是不包括i,j了啊)的最优值,那么
dp[i][j]=min(dp[i][k]+dp[k][j]),其中k为区间i,j中最后删除的元素,(i<k<j);
有了状态转移方程,实现起来就很方便了啊。
我用了迭代和记忆化搜索两种方式实现:
1,迭代代码(运行时间0Ms)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 #define INF 10000100 7 int dp[110][110]; 8 int a[110]; 9 void init() 10 { 11 for(int i=0;i<110;i++) 12 for(int j=0;j<110;j++) 13 dp[i][j]=INF; 14 for(int i=0;i<110;i++) 15 dp[i][i+1]=0; 16 memset(a,0,sizeof(a)); 17 } 18 int main() 19 { 20 int n; 21 while(scanf("%d",&n)!=EOF) 22 { 23 init(); 24 for(int i=0;i<n;i++) 25 cin>>a[i]; 26 for(int j=2;j<n;j++) 27 for(int i=j-2;i>=0;i--) 28 for(int k=i+1;k<j;k++) 29 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]); 30 cout<<dp[0][n-1]<<endl; 31 } 32 return 0; 33 34 }
2,记忆化搜索的方式(运行时间16MS)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 #define INF 100001000 7 int dp[110][110]; 8 int a[110]; 9 int dfs(int i,int j) 10 { 11 int sum=0; 12 if(dp[i][j]<INF) return dp[i][j]; 13 if(j==i+2) return dp[i][j]=a[i]*a[i+1]*a[j]; 14 if(j==i+1) return dp[i][j]=0; 15 for(int k=i+1;k<j;k++) 16 { 17 sum=dfs(i,k)+dfs(k,j)+a[i]*a[j]*a[k]; 18 dp[i][j]=min(dp[i][j],sum); 19 } 20 return dp[i][j]; 21 } 22 int main() 23 { 24 int n; 25 while(scanf("%d",&n)!=EOF) 26 { 27 int sum; 28 for(int i=0;i<n;i++) 29 scanf("%d",&a[i]); 30 for(int i=0;i<110;i++) 31 for(int j=0;j<110;j++) dp[i][j]=INF; 32 for(int k=1;k<n-1;k++) 33 { 34 sum=dfs(0,k)+dfs(k,n-1)+a[0]*a[n-1]*a[k]; 35 dp[0][n-1]=min(dp[0][n-1],sum); 36 } 37 cout<<dp[0][n-1]<<endl; 38 } 39 return 0; 40 }