c++踩方格-動態規劃基礎題

Danlis發表於2024-05-12

有一個方格矩陣,矩陣邊界在無窮遠處。我們做如下假設:
a、每走一步時,只能從當前方格移動一格,走到某個相鄰的方格上;
b、走過的格子立即塌陷無法再走第二次;
c、只能向北、東、西三個方向走;
請問:如果允許在方格矩陣上走n步,共有多少種不同的方案。2種走法只要有一步不一樣,即被認為是不同的方案。
輸入格式
允許在方格上行走的步數n(n≤20)。
輸出格式
計算出的方案數量。
樣例:1->3;2->7;3->17。

這道題在最初找第三步的時候,只找到15條,一直很懵逼,怎麼網上答案都是17條。後來才發現是我漏了,漏的是和2->3和0->1的路線中3和1重疊,將那個3砍掉了。

這是第二步的路線圖,圓形是起點,四邊形是第一步的落點,五邊形是第二步的落點。
實際上到了第二步,大概的一個關係能夠確定,

這是第三步的路線圖,三角形是第三步的落點,主要是紅色標識的地方,這兩個三角形,由於路線不同,不會出現坍塌,要計入的。
接下來就是分析關係了。
初始狀態F[0]=1,
走了一步後F[1]=3,
走了兩步後F[2]=7,
走了三步後F[3]=17。

走第二步的時候,能夠發現所有菱形都至少產生了兩個方向的五邊形,其中一個菱形產生了三個方向的五邊形。F[2]=32+1
走第三步的時候,能夠發現所有菱形都至少產生了兩個方向的三角形,而有三處菱形產生了三個方向的五邊形。F[3]=7
2+3
根據畫圖,能夠發現,上一步的基礎上,向上和向左(或者向右)都是存在的,有2F[i-1]。那麼多出來的向左(或者向右)是由哪部分產生?
是上上一步的向上箭頭產生的圖形,才擁有多朝左(或者右)的分支。
比如紅圈圈出來的五邊形以及頂部的五邊形,都是菱形向上箭頭產生出來的,而他們都擁有三個分支。往前看,第二步中菱形有三個分支的那處,也是向上箭頭產生的。如果對於資料還是不夠確定規律,可以繼續畫第四步,進行驗證。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int f[21]={1, 3, 7, 17}, n;
    cin >> n;
    for(int i=3;i<=n;i++){
        f[i]=2*f[i-1]+f[i-2];
    }
    cout << f[n] << endl;
    return 0;
}

遞迴寫法

#include<bits/stdc++.h>
using namespace std;

int dfs(int n){
	if(n<1) return 1;
	if(n==1) return 3;
	if(n==2) return 7;
	return 2*dfs(n-1)+dfs(n-2);
}

int main(){
	int n;
	cin >> n;
	cout << dfs(n) << endl;
	return 0;
}

上面那種遞迴,dfs(2)至少會進入兩次,所以可以記憶化搜尋

#include <bits/stdc++.h>
using namespace std;

int dp[21] = {1, 3, 7};

int dfs(int n) {
	if (n < 1) return 1;
	if (n == 1) return 3;
	if (n == 2) return 7;
	if (dp[n - 1] == 0)  dp[n - 1] = dfs(n - 1);
	if (dp[n - 2] == 0)  dp[n - 2] = dfs(n - 2);
	return 2 * dp[n - 1] + dp[n - 2];
}

int main() {
	int n;
	cin >> n;
	cout << dfs(n) << endl;
	return 0;
}

總的來說,肯定還是第一種使用陣列儲存更便捷。

相關文章