题意:输入一张n*m的地图,地图上代表着一个数字,然后开始走,向下只能移动一步,向右可以走到这个列数是当前列数的倍数或者是走一步。
好吧,我还分不清这个跟dfs什么的……
感觉这个题也不是很难的样子,脑子里就是一片浆糊。
建一张map,存入各个点的值,然后再建一张dp,初始时都是0,然后每个点都记为没有被访问过,从第一个格子开始访问,依次遍历每一个格子,对于每一个格子,都是算好,它能够到达的每一个地方,然后现有的值…
终于还是看了题解才懂,上面的想法是不对的,应该反过来想,把遍历到的每一个格子都当做终点,然后找能到达它的所有的格子中最大的那个,其实这才是dp的精髓所在,就是把当前要解决的问题当做是最终的解,或者说是把大问题原封不动地缩小。
☟AC代码
#include<iostream>
using namespace std;
#include<algorithm>
#include<string.h>
int main()
{
int c;
scanf("%d",&c);
while(c--)
{
int n,m;//n行,m列
scanf("%d%d",&n,&m);
int map[25][1005];
int dp[25][1005];
int i,j;
for(i=0;i<=n;i++)
dp[i][0]=-999999;
for(i=0;i<=m;i++)
dp[0][i]=-999999;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&map[i][j]);
dp[0][1]=0;
dp[1][0]=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
int k;
/*for(k=2;k<=m;k++)
{
if(j&k==0)
dp[i][j]=max(dp[i][j],dp[i][k]);
}感觉还不是很懂*/
for(k=2;k<=m;k++)
{
if(j/k==(double)j/k)
dp[i][j]=max(dp[i][j],dp[i][j/k]);
}
dp[i][j]=dp[i][j]+map[i][j];
}
/*for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
printf("%d ",dp[i][j]);
printf("\n");
}*/
printf("%d\n",dp[n][m]);
}
return 0;
}