POJ 1651 Multiplication Puzzle(구간 DP)

1450 단어 dppojACM-ICPC
비교적 고전적인 구간 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
",ans); } return 0; }

좋은 웹페이지 즐겨찾기