poj 1651 区间dp

题意:

n个数字组成的序列,每次取出一个数字,这个数字不能是最左端或最右端的数字,取第i个数字需要的代价为a[i-1] * a[i] * a[i+1],最后只剩下最左端和最右端的数字。问最小代价是多少。3 <= n <= 100。

题解:

1.dp[i][j]表示[i , j]区间取完(i , j)区间的数字的最小代价

2.dp[i][j] = min(dp[i][j] , dp[i][k] + dp[k][j] + a[i] * a[k] * a[j])。(i <= k <= j)

3.注意初始化。区间大小不同,初始化的内容不同。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 105
#define inf 0x3f3f3f3f 
using namespace std ;
int main()
{
	int i , j , k , d , l , r ;
	int n ;
	int a[N] ;
	int dp[N][N] ;
	scanf("%d" , &n) ;
	for(i = 1 ; i <= n ; i ++)
	   scanf("%d" , &a[i]) ;
	memset(dp , inf , sizeof(dp)) ;
	for(i = 1 ; i <= n ; i ++)
	   dp[i][i] = 0 ;
	for(i = 1 ; i <= n - 1 ; i ++)
	   dp[i][i + 1] = 0 ;
	for(i = 1 ; i <= n - 2 ; i ++)
	   dp[i][i + 2] = a[i] * a[i + 1] * a[i + 2] ;
	for(d = 3 ; d <= n - 1 ; d ++)
	   for(l = 1 ; l + d <= n ; l ++)
	   {
	   	 r = l + d ;
	   	 for(k = l ; k <= r ; k ++)
	   	   dp[l][r] = min(dp[l][r] , dp[l][k] + dp[k][r] + a[l] * a[k] * a[r]) ; 	
	   }
	printf("%d" , dp[1][n]) ;
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/87933228