UVALive 4212 Candy

ACM ICPC South American Regional 2008

 题目大意:给定一个矩阵,每个元素有一个值,每次取一个元素都会使得当前元素左右两个相邻项变为零,上下两行变为零,如图阴影部分所示,求最大能取到的值之和。

 解法:我竟然没有看出来是双重动规,果然太久不做动规了。当时还脑残的写了个四维的(虽然有三维的取值范围都是0,1),最后降到三维,然后wa了一次改了改之后AC了。正确的解法应该是每列dp一次,算出当前行的最优值,然后再用这个值按行dp。f[i]=max{f[i-1],f[i-2]+a[i]}空间上其实可以优化很多,dp数组只要开到3就好了,滚动一下即可。我没有滚动,直接开了两个MAXN的一维数组,然后每次用之前习惯性的memset了一下,没想到居然超时了,取消memset之后就过了。看来要慎用memset,如果明显知道不会出现新旧值混用的情况,就不必要memset了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <utility>
 7 #include <cstring>
 8 #include <fstream>
 9 #include <string>
10 using namespace std;
11 const int MAXN=100005;
12 int f[MAXN],g[MAXN],a[MAXN];
13 int main(int argc, char* argv[])
14 {
15     int m,n;
16     while(scanf("%d%d",&m,&n),(m!=0&&n!=0))
17     {
18         //memset(g,0,sizeof(g));
19         for(int i=1;i<=m;i++)
20         {
21             for(int j=1;j<=n;j++)
22                 scanf("%d",&a[j]);
23         //    memset(f,0,sizeof(f));
24             f[1]=a[1];
25             for(int j=2;j<=n;j++)
26                 f[j]=max(f[j-1],f[j-2]+a[j]);
27             if(i==1)
28                 g[1]=f[n];
29             else
30                 g[i]=max(g[i-1],g[i-2]+f[n]);
31         }
32         cout<<g[m]<<endl;
33     }
34 }
posted @ 2012-05-02 01:07  jzlikewei  阅读(246)  评论(0编辑  收藏  举报