您的位置:首页 > 其它

HDOJ 1244 记忆搜索

2012-08-14 21:55 281 查看
第一次,只用了简单地深搜,超时。于是自然就想到记忆搜索,用了就过啦。

ints是一维数组,保存所有数字。segs是一位数组,保存所有数段的长度。

ans是二维数组。ans[i][j]保存以第i个数字开始(但第i个数字不一定被取到,只是从第i个数字开始考虑),计算j,j+1...m段数段之和的最大值。本题要求的便是ans[1][1]。

ans[i][j]=max{sum+ans[i+segs[j]][j+1],ans[i+1][j]}。max{}中的两个数的区别就在于,是否以第i个数作为第j个数段的起始数字。

#include <iostream>
using namespace std;

const int N = 1005;
const int M = 25;
int ans
[M],segs[M],ints
;
int n,m;

int DFS(int posInt,int posSeg)
{
if (ans[posInt][posSeg] != -1)
return ans[posInt][posSeg];
//已经用完了n个数 或 分完m个数段了
if (posSeg > m || posInt > n)
{
ans[posInt][posSeg] = 0;
return ans[posInt][posSeg];
}
//判断,即使取了posInt位置的数,能不能取完余下的数段
int remainedInts = n - posInt + 1;
int remainedSegs = 0;
for (int i = posSeg;i <= m;i ++)
remainedSegs += segs[i];
//余下的数段的长度之和比余下的数字的个数还大
if (remainedSegs > remainedInts)
{
ans[posInt][posSeg] = 0;
return ans[posInt][posSeg];
}
//若能走到这一步,说明posInt位置的数可以不作为第posSeg个数段的起始数字
int max;
//以第posInt个数为起始,取seg[posSeg]个连续的数的和
int sum = 0;
for (int i = posInt;i < posInt + segs[posSeg];i ++)
sum += ints[i];
max = sum + DFS(posInt + segs[posSeg],posSeg + 1);
//以第posInt + 1个数为起始,取seg[posSeg]个连续的数的和
int temp = DFS(posInt + 1,posSeg);
max = max > temp ? max : temp;
ans[posInt][posSeg] = max;
return ans[posInt][posSeg];
}

int main ()
{
while (scanf("%d",&n) != -1 && n != 0)
{
memset(ans,-1,sizeof(ans));
scanf("%d",&m);
for (int i = 1;i <= m;i ++)
scanf("%d",&segs[i]);
for (int i = 1;i <= n;i ++)
scanf("%d",&ints[i]);
printf("%d\n",DFS(1,1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: