1. 程式人生 > 其它 >DP 計蒜客-牆壁塗色

DP 計蒜客-牆壁塗色

技術標籤:演算法與資料結構

蒜頭君覺得白色的牆面好單調,他決定給房間的牆面塗上顏色。他買了 3 種顏料分別是紅、黃、藍,然後把房間的牆壁豎直地劃分成 n 個部分,蒜頭希望每個相鄰的部分顏色不能相同。他想知道一共有多少種給房間上色的方案。

首先建立DP陣列 dp[60][3],dp[i][0]表示第i個位置放置紅色,以此類推。
則如果不考慮牆壁的迴圈性帶來的最後一塊與第一塊的衝突,有如下狀態轉移:

		dp[i][1]=dp[i-1][2]+dp[i-1][0];
        dp[i][2]=dp[i-1][0]+dp[i-1][1];
        dp[i][0]=dp[i-1][
1]+dp[i-1][2];

現在只需要求出最後一塊與第一塊衝突的方案數,減去該方案數即可。
牆壁染色情況(第一塊染紅色)示意圖如下:
在這裡插入圖片描述

num_0表示每層0的個數,num_1表示每層非0的個數,則有如下狀態轉移:

		long long tmp=num_0;
        num_0=num_1;
        num_1+=tmp*2;

則ans=dp[n][0]+dp[n][1]+dp[n][2]-num_0*3;
AC程式碼:

#include<iostream>

using namespace std;

int main(){
    long long dp[60][3]=
{0},n; cin>>n; dp[1][0]=dp[1][1]=dp[1][2]=1; for(int i=2;i<=n;i++){ dp[i][1]=dp[i-1][2]+dp[i-1][0]; dp[i][2]=dp[i-1][0]+dp[i-1][1]; dp[i][0]=dp[i-1][1]+dp[i-1][2]; } long long ans=dp[n][0]+dp[n][1]+dp[n][2]; long long num_0=1,num_1=0; for(int i=1;
i<n;i++){ long long tmp=num_0; num_0=num_1; num_1+=tmp*2; } ans-=num_0*3; cout<<ans; return 0; }