来源:http://acm.hdu.edu.cn/showproblem.php?pid=1078
一开始把最多走k步理解成每走一步有四种方向的选择,所以就思考把图转化为一个按奶酪数排序的一维数组
对这个一维数组进行深搜,最后得到了结果但超时了。
后面借鉴了一下别人的代码,发现走k步是只能连续横着走或者竖着走,这就可以用通常的遍历手段,再加上动态规划的思想进行解题。
有关记忆化搜索的解答:http://blog.youkuaiyun.com/urecvbnkuhbh_54245df/article/details/5847876
超时的代码:
#include<stdio.h>
#include<string>
#include<algorithm>
#include<math.h>
using namespace std;
struct point
{
int x,y;
int cheese;
};
point p[10005];
int map[105][105];
int n,k,ans;
bool cmp(const point a,const point b)
{
return a.cheese<b.cheese;
}
int check(int pos)
{
int i,j;
int x1,y1;
for(i=pos+1;i<n*n;i++)
{
x1=p[i].x;y1=p[i].y;
if(abs(x1-p[pos].x)+abs(y1-p[pos].y)<=k)
{
return i;
}
}
return 0;
}
void dfs(int pos,int getch)
{
int flag,i;
int x1,y1;
flag=check(pos);
if(flag==0)
{
if(ans<getch)ans=getch;
return;
}
for(i=pos+1;i<n*n;i++)
{
x1=p[i].x;y1=p[i].y;
if(abs(x1-p[pos].x)+abs(y1-p[pos].y)<=k)
{
dfs(i,getch+p[i].cheese);
}
}
}
int main()
{
int i,j,l;
int a1,a2;
scanf("%d%d",&n,&k);
l=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
scanf("%d",&map[i][j]);
p[l].x=i;p[l].y=j;
p[l].cheese=map[i][j];
l++;
}
scanf("%d%d",&a1,&a2);
sort(p,p+n*n,cmp);
for(i=0;i<n*n;i++)
{
if(p[i].x==0&&p[i].y==0)break;
}
ans=0;
dfs(i,p[i].cheese);
printf("%d\n",ans);
return 0;
}
正确的代码:
#include<stdio.h>
#include<string>
#include<algorithm>
#include<math.h>
using namespace std;
int n,k;
int map[105][105];
int dp[105][105];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int dfs(int x,int y)
{
int x1,y1;
int i,j,ans=0,temp;
if(dp[x][y]>0)
return dp[x][y];
for(i=0;i<4;i++)
for(j=1;j<=k;j++)//只能一直朝一个方向走
{
x1=x+dir[i][0]*j;
y1=y+dir[i][1]*j;
if(x1>=0&&x1<n&&y1>=0&&y1<n&&map[x1][y1]>map[x][y])
{
temp=dfs(x1,y1);//倒做的“递归式动态规划”
if(ans<temp)ans=temp;
}
}
dp[x][y]=ans+map[x][y];//加上此点的奶酪数
return dp[x][y];
}
int main()
{
int i,j,a1,a2;
scanf("%d%d",&n,&k);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
scanf("%d",&map[i][j]);
}
scanf("%d%d",&a1,&a2);
memset(dp,0,sizeof(dp));
dfs(0,0);
printf("%d\n",dp[0][0]);
return 0;
}