傳送門
這道題有好多好多種做法呀……先說一下最暴力的,o(n^4的做法)
我們相當於要找兩條從左上到右下的路,使路上的數字和最大。所以其實路徑從**開始走並不重要,我們就直接假設全部是從左上出發的好啦。設dp[i][j][p][q]表示第一條路列舉到點(i,j),第二條路列舉到點(p,q)時,當前能取到的最大值。
這樣dp方程很顯然,就是dp[i][j][p][q] = max(dp[i-1][j][p-1][q],dp[i][j-1][p-1][q],sp[i-1][j][p][q-1],dp[i][j-1][p][q-1]) + a[i][j] + a[p][q].如果i==p && j == q,那麼減去乙個a[i][j].最後dp[m][n][m][n]即為結果。
四層迴圈列舉,複雜度o(n^4),上一下**。
#include#include#include
#include
#define rep(i,a,n) for(ll i = a;i <= n;i++)
#define per(i,n,a) for(ll i = n;i >= a;i--)
#define enter putchar('\n')
using
namespace
std;
const
int m = 105
;typedef
long
long
ll;int
read()
while(ch >= '
0' && ch <= '9'
)
return ans *op;
}int m,n,dp[55][55][55][55],a[55][55
];int
main()
printf(
"%d\n
",dp[m][n][m][n]);
return0;
}
之後我們說一下怎麼優化。兩條路在走的時候,因為每次只能向右或者下走一格,所以兩者必然是在同一條斜對角線上的(一條從右上到左下的對角線)那麼我們就可以用對角線的橫縱座標和來表示當前dp到了**,之後每次只要列舉兩個點的橫座標就可以把路徑表示出來(也就是表示出來當前列舉的是哪兩個點)。這樣的話就可以把dp過程的時空降到三維的。
具體的寫法也很簡單,直接看一下**即可。
#include#include#include
#include
#include
#include
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
using
namespace
std;
typedef
long
long
ll;const
int m = 60
;int n,m,f[m][m],dp[120
][m][m],q[m];
intread()
while(ch >='
0' && ch <= '9'
)
return ans *op;
}int
main()}}
printf(
"%d\n
",dp[n+m][m][m]);
return0;
}
之後,時間複雜度基本已經不能再優化,不過空間複雜度卻可以優化到o(n^2)(其實還要再乘以乙個常數)
我們從剛才的三維dp的轉移過程來考慮一下。每次dp都是從上一條對角線上的元素轉移過來,和其他的對角線沒有任何關係,相當於我們在每次dp的時候只需要考慮兩個,乙個是i,乙個是i-1,在i-1之前的其實已經沒有了任何作用。所以我們完全可以廢物再利用。因為每次i的值只改變1,所以可以使用按位與的方法把它變成0或者1,之後直接dp即可,而最後的答案就是dp[(m+n)&1][m][m].這樣空間複雜度又會降一維。本題的資料範圍小,如果資料範圍較大,滾動陣列對於空間的節省就極為有用了。
看一下**。
#include#include#include
#include
#include
#include
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
using
namespace
std;
typedef
long
long
ll;const
int m = 60
;int n,m,f[m][m],dp[2
][m][m];
intread()
while(ch >='
0' && ch <= '9'
)
return ans *op;
}int
main()}}
printf(
"%d\n
",dp[(n+m)&1
][m][m]);
return0;
}
NOIP2008傳紙條 DP 費用流
在乙個矩形上求兩條不相交的價值最大的路徑 常規dp題,略過 這道題可以作為費用流入門題,可以很好理解費用流的用途 1 找出方案可行 考慮最大流建圖方法 首先因為要找不想交的兩條路徑,我們可以限制每個點只被選擇一次,對於點的限制一般是拆點的套路。將乙個點i拆分為2個點,i和i 並且連邊權為1,這樣就可...
Noip2008傳紙條題解
仍是多執行緒dp,這次直接斜著讀入,方便寫dp方程。以6 4的圖為例,讀入順序如表 從左至右,從上至下,不用管那些0 for int i 1 i m i for int j 1 j n j read map i j 1 i 00 0000 0000 00 1,4 2,4 3,4 4,4 5,4 6,...
動態規劃入門 NOIP2008 傳紙條
小淵和小軒是好朋友也是同班同學,他們在一起總有談不完的話題。一次素質拓展活動中,班上同學安排做成乙個m行n列的矩陣,而小淵和小軒被安排在矩陣對角線的兩端,因此,他們就無法直接交談了。幸運的是,他們可以通過傳紙條來進行交流。紙條要經由許多同學傳到對方手裡,小淵坐在矩陣的左上角,座標 1,1 小軒坐在矩...