记忆化搜索
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::getline;
using std::make_pair;
using std::greater;
const int INFI((INT_MAX-1) >> 1);
int table[110][110];
bool vis[110][110];
int sum[110];
int dfs(int l, int r)
{
if(vis[l][r])
return table[l][r];
int &cur = table[l][r];
cur = sum[r]-sum[l-1];
for(int i = l+1; i <= r; ++i)
cur = max(cur, sum[r]-sum[l-1]-dfs(i, r));
for(int i = r-1; i >= l; --i)
cur = max(cur, sum[r]-sum[l-1]-dfs(l, i));
vis[l][r] = true;
return cur;
}
int main()
{
int n, temp;
while(scanf("%d", &n), n)
{
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; ++i)
{
scanf("%d", &temp);
sum[i] = sum[i-1]+temp;
}
dfs(1, n);
printf("%d\n", table[1][n]-(sum[n]-table[1][n]));
}
return 0;
}
递推求解
状态转移方程:
table[i][j] = sum[j]-sum[i-1]-min( min(table[i][k]) (i <= k < j), min(table[k][j]) (i < k <= j), 0);
其中 设f[i][j] = min(table[k][j]) ( i<= k <= j) g[i][j] = min(table[i][k]) ( i<= k <= j)
则状态转移方程可转换为 table[i][j] = sum[j]-sum[i-1]-min(g[i][j-1], f[i+1][j], 0)
其中f[i][j] = min(table[i][j], f[i+1][j]), g[i][j] = min(table[i][j], g[i][j-1])可以在求解table[i][j]的时候一同递推求解,所以时间复杂下降到了O(n^2)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::getline;
using std::make_pair;
using std::greater;
const int INFI((INT_MAX-1) >> 1);
int table[110][110], f[110][110], g[110][110];
int arr[110], sum[110];
int main()
{
int n;
while(scanf("%d", &n), n)
{
for(int i = 1; i <= n; ++i)
{
scanf("%d", arr+i);
sum[i] = sum[i-1]+arr[i];
}
for(int i = 1; i <= n; ++i)
table[i][i] = f[i][i] = g[i][i] = arr[i];
for(int l = 2; l <= n; ++l)
{
int temp = n-l+1;
for(int i = 1; i <= temp; ++i)
{
int j = i+l-1;
int m = 0;
m = min(m, min(f[i+1][j], g[i][j-1]));
table[i][j] = sum[j]-sum[i-1]-m;
f[i][j] = min(table[i][j], f[i+1][j]);
g[i][j] = min(table[i][j], g[i][j-1]);
}
}
printf("%d\n", table[1][n]-(sum[n]-table[1][n]));
}
return 0;
}