# 洛谷OJ：P1880 [NOI1995]石子合并(DP)

Problem1:dp[i][j] = min{k|dp[i][j], dp[i][k]+dp[k+1][j]+w(i, j)}

Problem2: dp[i][j] = max{k|dp[i][j], dp[i][k]+dp[k+1][j]+w(i, j)}

/**
*	题目: 洛谷OJ：P1880 [NOI1995]石子合并
*	题型: DP
**/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

const int maxn = 200+10;
int dp[maxn][maxn], a[maxn], n, ans = 0x3f3f3f3f;

int w(int i, int j) {
return a[j] - a[i-1];
}

int main()  {
/************input**************/
cin >> n;
for(int i = 1; i <= n; i++)	{
cin >> a[i];
a[i+n] = a[i];
}
for(int i = 2; i <= 2*n; i++) a[i] += a[i-1];
/*******************************/
//Problem1
ans = 0x3f3f3f3f;
for(int i = 2*n; i >= 1; i--) {
for(int j = i+1; j <= n+i+1 && j <= 2*n; j++) {
dp[i][j] = 0x3f3f3f;
for(int k = i; k + 1 <= j; k++) {
dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]+ w(i,j));
}
}
}
for(int i = 1; i <= n; i++) ans = min(ans, dp[i][i+n-1]);
cout << ans << endl;
//Problem2
memset(dp, 0, sizeof(dp)); ans = 0;
for(int i = 2*n; i >= 1; i--) {
for(int j = i; j <= n+i-1 && j <= 2*n; j++) {
for(int k = i; k + 1 <= j; k++) {
dp[i][j] = max(dp[i][j], dp[i][k]+dp[k+1][j]+ w(i,j));
}
}
}
for(int i = 1; i <= n; i++) ans = max(ans, dp[i][i+n-1]);
cout << ans << endl;
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120