dfs:
深搜深搜
见都是动规的帖子,来来来,贴一个深搜的题解(手动滑稽)。。。
这道题深搜的最优方法就是两种方案同时从起点出发。因为如果记录完第一种方案,再计算第二种方案,不可控的因素太多了,大多都不是最优解→_→,但两种方案同时执行就行,因为这可以根据当前的情况来判断最优。
总的来说,每走一步都会有四个分支(你理解成选择或者情况也可以):
1、两种都向下走
2、第一种向下走,第二种向右走
3、第一种向右走,第二种向下走
4、两种都向右走
每走一步走枚举一下这四种情况,因为在每个点的方案具有唯一性(也就是在某个点走到终点的取数方案只有一个最优解,自己理解一下),所以我们可以开一个数组来记录每一种情况,当重复枚举到一种情况时就直接返回(对,就是剪枝),大大节省了时间(不然会超时哦~)。深搜和动归的时间复杂度时一样的!
附代码:
#include<iostream>
using namespace std;
int N=0;
int s[15][15],f[11][11][11][11];
int dfs(int x,int y,int x2,int y2)
{
if (f[x][y][x2][y2]!=-1) return f[x][y][x2][y2];
if (x==N&&y==N&&x2==N&&y2==N) return 0;
int M=0;
if (x<N&&x2<N) M=max(M,dfs(x+1,y,x2+1,y2)+s[x+1][y]+s[x2+1][y2]-s[x+1][y]*(x+1==x2+1&&y==y2));
if (x<N&&y2<N) M=max(M,dfs(x+1,y,x2,y2+1)+s[x+1][y]+s[x2][y2+1]-s[x+1][y]*(x+1==x2&&y==y2+1));
if (y<N&&x2<N) M=max(M,dfs(x,y+1,x2+1,y2)+s[x][y+1]+s[x2+1][y2]-s[x][y+1]*(x==x2+1&&y+1==y2));
if (y<N&&y2<N) M=max(M,dfs(x,y+1,x2,y2+1)+s[x][y+1]+s[x2][y2+1]-s[x][y+1]*(x==x2&&y+1==y2+1));
f[x][y][x2][y2]=M;
return M;
}
int main()
{
cin>>N;
for(int a=0;a<=N;a++)
for(int b=0;b<=N;b++)
for(int c=0;c<=N;c++)
for(int d=0;d<=N;d++) f[a][b][c][d]=-1;
for(;;)
{
int t1=0,t2=0,t3=0;
cin>>t1>>t2>>t3;
if(t1==0&&t2==0&&t3==0) break;
s[t1][t2]=t3;
}
cout<<dfs(1,1,1,1)+s[1][1];
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,x,y,val,ans=0,maxn,f[12][12][12][12],a[12][12];
int main(){
scanf("%d",&n);
memset(a,0,sizeof a);
while(1){
scanf("%d%d%d",&x,&y,&val);
if(x==0&&y==0&&val==0)break;
a[x][y]=val;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
for(int l=1;l<=n;l++){
f[i][j][k][l]=max(f[i-1][j][k-1][l],max(f[i][j-1][k-1][l],max(f[i-1][j][k][l-1],f[i][j-1][k][l-1])))+a[i][j]+a[k][l];
if(i==k&&j==l)f[i][j][k][l]-=a[i][j];
}
}
}
}
printf("%d\n",f[n][n][n][n]);
return 0;
}