樹形DP 兔子跳躍之謎下

2022-08-20 18:21:12 字數 2737 閱讀 4928

題目描述

小生和小森在玩兔子之謎遊戲。有三隻兔子排成一排。知道每只兔子的初始位置,以及三個兔窩的位置。 

遊戲的規則是,重複以下步驟k次:選擇兩個不同的兔子a和b,分別位於a和b。a可以跳過b到達2*b-a的點:

跳躍是不允許其他小兔子已經在點2*b-a的位置上:

跳躍也不允許一次跳過乙個以上的兔子: 

現在小生和小森想要知道,k次操作之後,能否讓所有兔子都分別跳到乙個兔窩裡面。注意,第i個兔子並不一定要在第i個巢。並且輸出跳法的種數,數值可能很大,要對結果取模1000000007。只要有乙個跳躍是不同的,兩種方式被認為是不同的。

輸入

有多組測試資料: 

第一行,包含乙個整數num,表示測試資料的個數。(1<=num<=10)

每組測試資料, 

第一行三個整數,第二行三個整數,分別表示兔子的初始位置和兔窩的位置。兩組數值都是嚴格遞增給出。範圍均為[-10^18,10^18]。

最後乙個整數k。[1,100]。

輸出

共num行,

跳躍的種數。 

樣例輸入

80 5 8

0 8 11

10 5 8

0 8 11

30 5 8

0 8 11

25 8 58

13 22 64

580 1 2

1 2 3

1005 8 58

20 26 61

5867 281 2348

235 1394 3293

83-1000000000000000000 999999999999999998 999999999999999999

-1000000000000000000 999999999999999999 1000000000000000000

5樣例輸出

15

000537851168

167142023

29這道題一拿到不知道怎麼做,好像只能dfs

但是接著我們發現,三隻兔子有三種操作:兩隻兔子跳到中間(一種情況);乙隻兔子跳到外面(兩隻兔子跳到外面)。

可以把兔子間的跳躍抽象成乙個二插樹形結構

根節點:三隻兔子等距;兩隻兔子就跳不到中間啦

葉節點:中間那只兔子分別跳到左邊和右邊的情況

對於跳躍的方案數,只是詢問在一棵二叉樹上兩個節點間之間用k步跳躍所能達到的方案數

我們用dp[i][j][k]表示初始節點a離lca  i步,結束點b離lca  j步,還剩下k步時的方案總數

。為了方便處理,我們假設b節點不動(這很重要,也很巧妙)

當i>0時 讓a向上下走dp[i][j][k]+=dp[i-1][j][k-1]+2*dp[i+1][j][k-1]

當i=0時 讓a向上下走(向上走時lca為a)dp[0][j][k]+=dp[0][j+1][k-1]+dp[0][j-1][k-1]+dp[1][j][k-1]

當i=j=0時 讓a向上下走 dp[0][0][k]=dp[0][1][k-1]+dp[1][0][k-1]*2;

根據定義,j>b離lca的距離時dp為0;**借鑑自lhq大神的blog

#include#include

#include

#include

using

namespace

std;

typedef

long

long

ll;#define mod 1000000007

const

int n=107

;struct

note

}point,point1,fa[

2][n];

intdp[n][n][n];

intk,deep_a,deep_b;

bool

ok(note s)

note make(note s)

else

}int dp(int i,int j,int

k)

else

if (i==0&&j>0

)

else

if (i>0 && j==0

)

else

if (i==0&&j==0

)

return

dp[i][j][k];

}int

main()

for(int i=1;i<=k&&ok(fa[1][i-1]);i++)

bool flag=1

;

int t1=-1,t2=-1

;

for(int i=0;i<=deep_a&&flag;i++)

for(int j=0;j<=deep_b&&flag;j++)

}if(t1==-1

)

dp[0][0][0]=1

; memset(dp,-1,sizeof

(dp));

printf(

"%d\n

",dp(t1,t2,k));

}return

0;

}

兔子跳躍之謎下

bzoj許可權題,但這個 可免費評測 題目描述 小生和小森在玩兔子之謎遊戲。有三隻兔子排成一排。知道每只兔子的初始位置,以及三個兔窩的位置。遊戲的規則是,重複以下步驟k次 選擇兩個不同的兔子a和b,分別位於a和b。a可以跳過b到達2 b a的點 跳躍是不允許其他小兔子已經在點2 b a的位置上 跳躍...

樹形DP 樹形DP四例

是時候練一下dp了!我的題單 portkey f u,if fu,i 表示以u uu為根節點的子樹中保留i ii條樹枝的最大蘋果數 f u,i max f max f fu,i max這些題是菜,但也不能輕視啊!include using namespace std define in read i...

HLOJ 樹形DP前置 DFS(樹形DP入門)

給定一棵 n nn 個點的樹,根為 t tt求每個點的父親是哪個點,t tt 的父親輸出 0 00第一行兩個整數 n,t n,tn,t接下來 n 1 n 1n 1 行,每行兩個整數 x,y x,yx,y,表示 x,y x,yx,y 之間有一條邊 n nn 行,第 i ii 行乙個整數,表示 i ii...