NYOJ 737 (石子合并)
Posted i am back
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NYOJ 737 (石子合并)相关的知识,希望对你有一定的参考价值。
该题是一道DP题,核心思想如下:
某个区间一定是这个区间内的某两个子区间合成的(这两个子区间互补,即这两个区间加起来等于大区间),
所以我们枚举所有的情况,取个最大值即可。因为最初是从2堆石子开始无法选择,到数量大了就可以择优,体现出DP的优势。
DP[ i ] [ j ]表示 i 到 j 区间的最优合并值。
则由上述思想转移方程如下:
dp[ i ][ j ] = min( dp[ i ][ j ], dp[ i ][ k ] + dp[k + 1][ j ] + sum[ i ][ j ] ) (i <= k <= j - 1)。
#include<iostream> #include<cstdio> #include<string.h> using namespace std; int n, s[205][205], a[205], f[205][205]; int main() { while(scanf("%d", &n) != EOF) { memset(s, 0, sizeof s ); memset(a, 0, sizeof a ); memset(f, 0, sizeof f ); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) { for(int j = i; j <= n; j++) { f[i][j] = 0x3f3f3f3f;//初值赋无限大 for(int k = i; k <= j; k++) s[i][j] = s[i][j] + a[k]; } } for(int i = 1; i <= n; i++) f[i][i] = 0;//自身初值为0 for(int i = 1; i < n; i++) { for(int j = 1; j <= n-i; j++) { for(int k = j; k <= i + j - 1; k++) { if(f[j][i+j] > f[j][k] + f[k+1][i+j]+s[j][i+j]) f[j][i+j] = f[j][k] + f[k+1][i+j]+s[j][i+j]; } printf("f[%d][%d] = %d\n", j, i+j, f[j][i+j]); } } printf("%d\n", f[1][n]); } return 0; }
以上是关于NYOJ 737 (石子合并)的主要内容,如果未能解决你的问题,请参考以下文章