1. 程式人生 > >動態規劃-擊鼓傳花

動態規劃-擊鼓傳花

【題目】

學校聯歡晚會的時候,為了使每一個同學都能參與進來,主持人常常會帶著同學們玩擊鼓傳花的遊戲。遊戲規則是這樣的:n個同學坐著圍成一個圓圈,指定一個同學手裡拿著一束花,主持人在旁邊背對著大家開始擊鼓,鼓聲開始之後拿著花的同學開始傳花,每個同學都可以把花傳給自己左右的兩個同學中的一個(左右任意),當主持人停止擊鼓時,傳花停止,此時,正拿著花沒傳出去的那個同學就要給大家表演一個節目。
 聰明的小賽提出一個有趣的問題:有多少種不同的方法可以使得從小賽手裡開始傳的花,傳了m次以後,又回到小賽手裡。對於傳遞的方法當且僅當這兩種方法中,接到花的同學按接球順序組成的序列是不同的,才視作兩種傳花的方法不同。比如有3
個同學1號、2號、3號,並假設小賽為1號,花傳了3次回到小賽手裡的方式有1->2->3->11->3->2->1,共2種。 輸入 輸入共一行,有兩個用空格隔開的整數n,m(3<=n<=301<=m<=30) 樣例輸入 3 3 輸出 輸出共一行,有一個整數,表示符合題意的方法數 樣例輸出 2 時間限制 C/C++語言:1000MS其它語言:3000MS 記憶體限制 C/C++語言:65536KB其它語言:589824KB

【solution】

package dynamic_planing;

import java.util.Scanner;

/**
 * 思路:
 * 設n個人第m次回到小賽手裡的情況為dp[m
][n] * dp[m][n]等於第m-1次傳遞到小賽左右兩邊的人的情況之和,即 dp[m][n] = dp[m-1][(n-1+n)%n] + dp[m-1][(n+1)%n] * 邊界值: * dp[1][2] = 1 dp[1][2] = dp[0][1] + dp[0][3] ----------> dp[0][1] = 1 * dp[1][n] = 1 dp[1][n] = dp[0][1] + dp[0][n-1] ----------> dp[0][1] = 1 其餘dp[0][i] = 0; * 真正的邊界值: * dp[0][1] = 1 dp[0
][i != 1] = 0; */ public class TransmitFlower { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); sc.close(); int[][] dp = new int[m+1][n+1]; dp[0][1] = 1; //dynamic planing for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if(j == 1){ dp[i][j] = dp[i-1][n] + dp[i-1][j+1]; }else if(j == n){ dp[i][j] = dp[i-1][j-1] + dp[i-1][1]; }else{ dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1]; } } } System.out.println(dp[m][1]); } }