数字三角形2
从三角形顶端走到最下面一行所经过数字的和sum mod 100要最大
一开始,我就想确定最后的值是最大的关键的地方在哪里,想老久也想不出,觉得这不可能的事情嘛,后来看了题解,原来这是类似于存在性验证的一类DP,即求出0...99哪个结果可能出现,然后取其中的最大值就是结果。
设状态vis[i][j][k]表示到(i,j)的时候能否达到k值,如果可以就==true。从下到上扫过去,对于每个(i,j)只可能从下一行的左边或右边上来,所以只需要遍历一遍下一行左边和右边所能得到的值k,然后vis[i][j][(k+a[i][j])%100] = true,这样到vis[1][1][]后,从0到99扫一遍vis[1][1][i]就能得到最大值
存在性的DP确实很强大很有用啊
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 26; 7 bool vis[maxn][maxn][100]; 8 int a[maxn][maxn]; 9 int main() 10 { 11 int n; 12 cin>>n; 13 for(int i = 1;i<=n;++i) 14 for(int j = 1;j<=i;++j) 15 scanf("%d",&a[i][j]); 16 memset(vis,false,sizeof(vis)); 17 for(int i = 1;i<=n+1;i++) 18 vis[n+1][i][0] = true; 19 for(int i = n;i>0;--i) 20 for(int j = 1;j<=i;++j) 21 for(int k = 0;k<100;++k) 22 { 23 if(vis[i+1][j][k])vis[i][j][(k+a[i][j])%100] = true; 24 if(vis[i+1][j+1][k])vis[i][j][(k+a[i][j])%100] = true; 25 } 26 for(int i = 99;i>=0;--i) 27 if(vis[1][1][i]){printf("%d\n",i);break;} 28 29 30 return 0; 31 }
时间: 2024-10-17 18:00:53