1. 程式人生 > >四角遞推(CF Working out,動態規劃遞推)

四角遞推(CF Working out,動態規劃遞推)

題目:假如有A,B兩個人,在一個m*n的矩陣,然後A在(1,1),B在(m,1),A要走到(m,n),B要走到(1,n),兩人走的過程中可以撿起格子上的數字,而且兩人速度不一樣,可以同時到一個點(哪怕這個點離A很近,離B很遠),現在A,B起碼相遇於一個點點,相遇點的數字A,B都得不到,求最後A,B總數字之和的最大值

B. Working out Summer is coming! It's time for Iahub and Iahubina to work out, as they both want to look hot at the beach. The gym where they go is a matrix
a with n lines and
m columns. Let number
a[i][j] represents the calories burned by performing workout at the cell of gym in the
i-th line and the j-th column.
Iahub starts with workout located at line 1 and column
1. He needs to finish with workout
a[n][m]. After finishing workout
a[i][j], he can go to workout
a[i + 1][j] or a[i][j + 1]. Similarly, Iahubina starts with workout
a[n][1] and she needs to finish with workout
a[1][m]. After finishing workout from cell
a[i][j], she goes to either
a[i][j + 1] or
a[i - 1][j].
There is one additional condition for their training. They have to meet in exactly one cell of gym. At that cell, none of them will work out. They will talk about fast exponentiation (pretty odd small talk) and then both of them will move to the next workout.
If a workout was done by either Iahub or Iahubina, it counts as total gain. Please plan a workout for Iahub and Iahubina such as total gain to be as big as possible. Note, that Iahub and Iahubina can perform workouts with different speed, so the number of
 cells that they use to reach meet cell may differs.
Input
The first line of the input contains two integers n and
m (3 ≤ n, m ≤ 1000). Each of the next
n lines contains m integers:
j-th number from i-th line denotes element
a[i][j] (0 ≤ a[i][j] ≤ 105).
Output
The output contains a single number — the maximum total gain possible.
Sample test(s)
Input
3 3
100 100 100
100 1 100
100 100 100   Output
800
/*
思路: 要找最大值,那麼只能有一個相遇點 如果用兩個陣列再來列舉相遇點是不可能的 所以比如說左上到右下,可以換成左上到相遇點,右下到相遇點 另一條路線也是如此 列舉各種可能的相交點,那麼從左下角走到相交點或者從左上角走到 相交點的各種情況很容易用for寫出來 可是從相交點到終點不好寫,因為相交點是列舉的, 相當於未知, 逆向思維:從相交點到終點==從終點到相交點 而終點只有兩個,遞推就是要從已知到未知 那麼這題就轉換成從四個邊角點到未知點 */ #include<bits/stdc++.h> using namespace std; #define
ll long long const ll maxn=1000+10; ll f[maxn][maxn]={0},dp1[maxn][maxn],dp2[maxn][maxn],dp3[maxn][maxn],dp4[maxn][maxn]; int main()//定義陣列f存基礎數字,dp1代表從左上角遞推 //dp2左下角,dp3右下角,dp4右上角 { //輸入環節 ll m,n; cin>>m>>n; for(ll i=1;i<=m;i++) for(ll j=1;j<=n;j++) { scanf(
"%lld",&f[i][j]); } //處理環節 dp1[1][1]=f[1][1];//對dp1邊緣賦值,即左邊和上邊兩面牆賦入初始值 for(ll i=2;i<=m;i++) dp1[i][1]+=f[i][1]+dp1[i-1][1]; for(ll j=2;j<=n;j++) dp1[1][j]+=f[1][j]+dp1[1][j-1]; dp2[m][1]=f[m][1];//對dp2邊緣賦值 for(ll i=m-1;i>=1;i--) dp2[i][1]+=f[i][1]+dp2[i+1][1]; for(ll j=2;j<=n;j++) dp2[m][j]+=f[m][j]+dp2[m][j-1]; dp4[1][n]=f[1][n];//對dp4邊緣賦值 for(ll i=2;i<=m;i++) dp4[i][n]+=f[i][n]+dp4[i-1][n]; for(ll j=n-1;j>=1;j--) dp4[1][j]+=f[1][j]+dp4[1][j+1]; dp3[m][n]=f[m][n];//對dp3邊緣賦值 for(ll i=m-1;i>=1;i--) dp3[i][n]+=f[i][n]+dp3[i+1][n]; for(ll j=n-1;j>=1;j--) dp3[m][j]+=f[m][j]+dp3[m][j+1]; for(ll i=2;i<=m;i++)//讓i從2到m,j從2到n for(ll j=2;j<=n;j++)//下面再通過調一下下標與i,j的關係實現同時處理四個陣列 { dp1[i][j]+=f[i][j]+max(dp1[i-1][j],dp1[i][j-1]); dp4[i][n-j+1]+=f[i][n-j+1]+max(dp4[i][n-j+1+1],dp4[i-1][n-j+1]); dp2[m-i+1][j]+=f[m-i+1][j]+max(dp2[m-i+1+1][j],dp2[m-i+1][j+1]); dp3[m-i+1][n-j+1]+=f[m-i+1][n-j+1]+max(dp3[m-i+1+1][n-j+1],dp3[m-i+1+1][n-i+1+1]); }//dp1從左下角開始遞推,dp2,3,4也從其他三個角開始遞推 ll ans=0; for(ll i=1;i<=m;i++)//這裡兩個for迴圈列舉相遇點 for(ll j=1;j<=n;j++) { ans=max(ans,dp1[i][j]+dp2[i][j]+dp3[i][j]+dp4[i][j]-4*f[i][j]); }//如果[i][j]是相遇點,那麼f[i][j]在dp1,dp2,dp3,dp4都被多拿了 //(相遇點的數字不能拿,所以要減去4*f[i][j]) cout<<ans<<endl; return 0; /*********************這裡預備一串程式碼輸出dp1到dp4後來的具體情況 可以自己用來檢驗dp1到dp4是否和自己想想的結果一樣 printf("\n"); for(ll i=1;i<=m;i++) for(ll j=1;j<=n;j++) { printf("%lld ",dp1[i][j]); if(j==3)printf("\n"); } printf("\n"); for(ll i=1;i<=m;i++) for(ll j=1;j<=n;j++) { printf("%lld ",dp2[i][j]); if(j==3)printf("\n"); } printf("\n"); for(ll i=1;i<=m;i++) for(ll j=1;j<=n;j++) { printf("%lld ",dp3[i][j]); if(j==3)printf("\n"); }printf("\n"); for(ll i=1;i<=m;i++) for(ll j=1;j<=n;j++) { printf("%lld ",dp4[i][j]); if(j==3)printf("\n"); }printf("\n"); ************************/ }