1. 程式人生 > >NOIP2000方格取數(洛谷,動態規劃遞推)

NOIP2000方格取數(洛谷,動態規劃遞推)

先上題目:

P1004 方格取數

 

下面上ac程式碼:

///如果先走第一個再走第二個不可控因素太多
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll f[11][11][11][11];
ll a[11][11];
int main()
{
    ios::sync_with_stdio(false);
    ll n,xx,yy,zz;
    cin>>n;
    while(scanf("%lld %lld %lld"
,&xx,&yy,&zz)==3&&!(xx==0&&yy==0&&zz==0)) a[xx][yy]=zz;//匯入基本資料 //我們需要f[n][n][n][n]作為答案,它表示走完兩次的總數 // f[1][1][1][1]=a[1][1];//這裡不用賦初值 for(ll i=1;i<=n;i++) for(ll j=1;j<=n;j++) for(ll x=1;x<=n;x++) for(ll y=1
;y<=n;y++) { f[i][j][x][y]=a[i][j]+a[x][y]+max(max(max(f[i-1][j][x-1][y],f[i-1][j][x][y-1]),f[i][j-1][x-1][y]),f[i][j-1][x][y-1]); // f[i][j][x][y]=max(f[i][j][x][y],f[i-1][j][x-1][y]+a[i][j]+a[x][y]); // f[i][j][x][y]=max(f[i][j][x][y],f[i-1][j][x][y-1]+a[i][j]+a[x][y]);
// f[i][j][x][y]=max(f[i][j][x][y],f[i][j-1][x-1][y]+a[i][j]+a[x][y]); // f[i][j][x][y]=max(f[i][j][x][y],f[i][j-1][x][y-1]+a[i][j]+a[x][y]); if(i==x&&j==y) f[i][j][x][y]-=a[i][j]; } cout<<f[n][n][n][n]<<endl; }
點選加號展開程式碼

 

然後講思路:

1.如果先走第一個,第一個走完了再走第二個會有很多不可控因素(我就摔在這個坑上)

2.這題其實可以看作兩個人同時走

每一回合有四種可能:

@1,兩個同時向右走

@2,兩個同時向下走

@3,第一個向右走,第二個向下走

@4,第一個向下走,第二個向右走

所以需要四個連環的for迴圈

用i,j表示第一個的座標,x,y表示第二個的座標

如果他們同時相遇,就相當於把一個格子的數字拿了兩次,再減掉這一次就好了

也就是:

if(i==x&&j==y)
      f[i][j][x][y]-=a[i][j];    

這裡的減就是數字拿多了,要扣的意思

 

然後遞推式有兩種寫法:

@1:

 f[i][j][x][y]=max(f[i][j][x][y],f[i-1][j][x-1][y]+a[i][j]+a[x][y]);
 f[i][j][x][y]=max(f[i][j][x][y],f[i-1][j][x][y-1]+a[i][j]+a[x][y]);
 f[i][j][x][y]=max(f[i][j][x][y],f[i][j-1][x-1][y]+a[i][j]+a[x][y]);
 f[i][j][x][y]=max(f[i][j][x][y],f[i][j-1][x][y-1]+a[i][j]+a[x][y]);

第一種遞推式的意思是考慮四種走法哪一種好,找出最大的,為每一格附上當前能有的最大數目,一直遞推就是答案了

@2:

f[i][j][x][y]=a[i][j]+a[x][y]+max(max(max(f[i-1][j][x-1][y],f[i-1][j][x][y-1]),f[i][j-1][x-1][y]),f[i][j-1][x][y-1]);

第二種和第一種一個意思,寫法不同而已

 

最後f[n][n][n][n]就是我們要的答案