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 }