您的位置:首页 > 其它

区间型动态规划 之 CODE[VS] 矩阵取数游戏 (2007年NOIP全国联赛提高组)

2015-11-03 15:08 507 查看
/*
分析:
对于n行输入,各行之间是独立的,只需要找到各行的最大值,它们的和即为答案。
由于:1<=n, m<=80,0<=aij<=1000,所以最大会出现 1000*(2^80) => 高精度计算

dp[i][j] := 每行取第i到j个数可得到的最大值。
对于输入的任一行a[m],第x次取数的状态转移为:
dp[i][j] = 2*max(dp[i+1][j]+arr[i],dp[i][j-1]+arr[j])
(正常取数是由外向内,但步长是由小到大,相当于取数是由内向外,所以2要乘在外面,这样倍数会自然乘上)

*/


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstddef>
#include <iterator>
#include <algorithm>
#include <locale>
#include <cmath>
#include <vector>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MaxN = 85;
const int MaxLen = 30;

int n, m;

struct node
{
int arr[MaxLen];
int len;
node ()
{
memset(arr, 0, sizeof(arr));
len = 0;
}
};

int arr[MaxN];

// a*2
node Mul(node a)
{
int carry = 0;
for (int i = 0; i < a.len; ++i)
{
a.arr[i] = (a.arr[i] << 1) + carry;
carry = a.arr[i] / 10;
a.arr[i] %= 10;
}
if (carry != 0)
{
a.arr[a.len] = carry;
++(a.len);
}
return a;
}

node Add(node a, int val)
{
int carry = 0;
for (int i = 0; i < a.len; ++i) {
a.arr[i] += (val % 10 + carry);
val /= 10;
carry = a.arr[i] / 10;
a.arr[i] %= 10;
}
while (val)
{
a.arr[a.len] += (val % 10 + carry);
val /= 10;
carry = a.arr[a.len] / 10;
a.arr[a.len] %= 10;
++(a.len);
}
if (carry)
{
a.arr[a.len] = carry;
++(a.len);
}
return a;
}

node Add(node a, node b)
{
node tmp;
int carry = 0;
int len = max(a.len, b.len);
for (int i = 0; i < len; ++i)
{
tmp.arr[i] = a.arr[i] + b.arr[i] + carry;
carry = tmp.arr[i] / 10;
tmp.arr[i] = tmp.arr[i] % 10;
++(tmp.len);
}
if (carry != 0)
{
tmp.arr[tmp.len] = carry;
++(tmp.len);
}

return tmp;
}

node Cmp(node a, node b)
{
if (a.len < b.len)
{
return b;
}
if (a.len > b.len)
{
return a;
}

for (int i = a.len - 1; i >= 0; --i)
{
if (a.arr[i] == b.arr[i]) continue;
if (a.arr[i] > b.arr[i])
{
return a;
}
else {
return b;
}
}
return a;
}

int main()
{
node ans;
cin >> n >> m;
for (int tn = 0; tn < n; ++tn)
{
node dp[MaxN][MaxN];
for (int tm = 0; tm < m; ++tm)
{
cin >> arr[tm];
// 初始化:dp[i][i] = (arr[i]<<1)
int tmp = (arr[tm] << 1);
// 不用while循环,防止 tmp=0
do
{
dp[tm][tm].arr[dp[tm][tm].len] = tmp % 10;
++(dp[tm][tm].len);
tmp /= 10;
} while (tmp);
}
for (int k = 1; k < m; ++k)
{
for (int i = 0; (i + k) < m; ++i)
{
/*node tmp1 = Add(dp[i + 1][i + k], arr[i]);
node tmp2 = Mul(Add(dp[i + 1][i + k], arr[i]));*/
dp[i][i + k] = Mul(Cmp(Add(dp[i + 1][i + k], arr[i]), Add(dp[i][i + k - 1], arr[i+k])));
}
}
ans = Add(ans, dp[0][m - 1]);
}
for (int i = ans.len - 1; i >= 0; --i)
{
cout << ans.arr[i];
}
cout << endl;

#ifdef HOME
cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
#endif
return 0;
}




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: