给一个n行n列的网格,每个格子里有一个1到9的数字。你需要从左上角走到右下角,其中每一步只能往上、下、左、右四个方向之一走到相邻格子,不能斜着走,也不能走出网格,但可以重复经过一个格子。为了美观,你经过的路径还必须关于“左下-右上”这条对角线对称。你的任务是统计所有合法路径中,数字之和最小的路径有多少条。
这道题在学校oj上数据出得比较小,但对于我这种渣渣来说还是还是需要好好考虑的。
思路:网格的左上角和右下角同时往中间搜,搜到同一个点,不过搜索的时候注意对称。
这个对称是左上角的网格往右搜,那么右下角的网格就往上搜;左上角的网格往下搜,那右下角的网格就往左搜;同理可知其它方向。
每搜索出一条对称路径便比对是否最优。
因为可以重复经过一个格子,四个方向的搜索就会出现无限搜索的情况((1,1)→(1,2)→(1,1)→……等情况),这个问题卡了很久还是没有好的解决方法。最终通过记录路径上数字之和来终止这种情况。
#include<iostream>
#include<string.h>
using namespace std;
int a[205][205];
int t;
long long mmin;
long long no=0;
void dfs(int a1,int b1,int a2,int b2,long long sum)
{
if(a1==a2&&b1==b2)
{
if(sum+a[a1][b1]==mmin)
{
no++;
}
else
if(sum+a[a1][b1]<mmin)
{
mmin=sum+a[a1][b1];
no=1;
}
}
else
{
sum+=a[a1][b1]+a[a2][b2];
if(sum<mmin)
{
if(a1+1<=t)
dfs(a1+1,b1,a2,b2-1,sum);
if(b1+1<=t)
dfs(a1,b1+1,a2-1,b2,sum);
if(a1-1>0)
dfs(a1-1,b1,a2,b2+1,sum);
if(b1-1>0)
dfs(a1,b1-1,a2+1,b2,sum);
}
}
}
int main()
{
int i,j;
while(1)
{
cin>>t;
if(t==0) break;
memset(a,0,sizeof(a));
mmin=1000000009;
no=0;
for(i=1;i<=t;i++)
for(j=1;j<=t;j++) cin>>a[i][j];
dfs(1,1,t,t,0);
cout<<no%1000000009<<endl;
}
return 0;
}
学校oj上数据小,这样能过,数据大了这题这样做应该就超时了。
我暂时只能做到这了。
链接是大神写的这道题的题解:http://blog.csdn.net/talak/article/details/8075223