POJ 1651 Multiplication Puzzle(区间DP)

来源:互联网 发布:爱数据网课程 编辑:程序博客网 时间:2024/05/17 21:48

一道比较经典的区间DP,和这题一样:点击打开链接

用dp[i][j] 表示消掉区间[i,j]内所有数字后的最优解。   那么状态转移为ans = min(ans,dp(i,k-1)+a[k]*a[i-1]*a[j+1]+dp(k+1,j)); 这个状态转移表示的是对于区间[i,j]最后杀k。  为什么要这么转移呢?  因为你选择的这个数字,其左右的数字会对其产生影响,而这样表示就可以巧妙的消除这个影响,而把问题转移给其子问题。既然最后选择k那么获得的分数自然就是a[k]*a[i-1]*a[j+1] 了。

细节参见代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<numeric>#include<functional>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<cassert>#include<complex>#include<iomanip>#include<deque>#include<map>#include<queue>using namespace std;typedef long long ll;const int maxn = 205;const int INF = 1000000000;int T,n,kase=0,a[maxn],b[maxn],d[maxn][maxn];int dp(int i, int j) {    if(i > j) return 0;    int& ans = d[i][j];    if(ans != -1) return ans;    ans = INF;    for(int k=i;k<=j;k++) ans = min(ans,dp(i,k-1)+a[k]*a[i-1]*a[j+1]+dp(k+1,j));    return ans;}int main() {    while(~scanf("%d",&n)) {        memset(d,-1,sizeof(d));        for(int i=1;i<=n;i++) scanf("%d",&a[i]);        a[n+1] = b[n+1] = 1;        int ans = dp(2,n-1);        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击