您的位置:首页 > 其它

poj 2948 Martian Mining dp

2013-04-14 19:39 309 查看
喜欢这样的题目
有一些思考的地方
关键是注意到一个地方
往左运,往上运的点都是连续的(原因自己想想就明白了)
否则不是最优的
有了这一点就可以dp了
dp[i][j]表示第i行,第一个向上的点是j时的最优解。
状态转移

for(int
k=j;k<=n+1;k++)

dp[i+1][k]=max(dp[i+1][k],dp[i][j]+sum1[i+1][k-1]+sum2[i+1][k]);

sum1,sum2表示两种矿连续的一段和

还有一点需要说明的,复杂度500*500*500超过一亿了,为什么可以过,第一常数很小,因为只进行一次运算和比较。第二k是从j开始循环的。所以实际的运算次数要比这个小得多。

#include
#include
#include
using namespace std;
const int maxn=555;
int dp[maxn][maxn],sum1[maxn][maxn],sum2[maxn][maxn];

int max(int a,int b)
{
if(a>b)
return(a);
return(b);
}

int main()
{
int n,m;
while(scanf("%d
%d",&n,&m),n&&m)
{

memset(dp,0,sizeof(dp));

memset(sum1,0,sizeof(sum1));

memset(sum2,0,sizeof(sum2));

for(int i=1;i<=n;i++)

for(int j=1;j<=m;j++)

{

scanf("%d",&sum1[i][j]);

sum1[i][j]+=sum1[i][j-1];

}

for(int i=1;i<=n;i++)

for(int j=1;j<=m;j++)

scanf("%d",&sum2[i][j]);

//
printf("hi");

for(int i=1;i<=n;i++)

for(int j=m;j>=1;j--)

sum2[i][j]+=sum2[i][j+1];

for(int i=0;i

for(int j=1;j<=n+1;j++)

{

for(int
k=j;k<=n+1;k++)

dp[i+1][k]=max(dp[i+1][k],dp[i][j]+sum1[i+1][k-1]+sum2[i+1][k]);

}

int ans=0;

for(int i=1;i<=n+1;i++)

ans=max(dp
[i],ans);

printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: