timus 1172. Ship Routes URAL 解題報告 組合DP

timus   1172. Ship Routes   URAL 解題報告

題目大意:有三個島,每個島上有n個城市,一個遊客想要遊覽遍三個島上的所有城市,最後再回到出發點…… 而且不能走陸路,因爲陸路上有食人族,水路的話只有不同島上的城市纔有……
求所有的可能的路徑……      
注意:如果一條路正好是迴文串,那麼只算一條!
因爲遊客已經到達一個城市了,這個城市可能在某個島上,是該島上的一個城市,你不知道是那個城市,但有一點你必須清楚,那就是這個城市已經確定了,你不能說他有n*3種可能了,他只有一種可能,即便你不知道他到底是哪個城市……
還有就是加入你從起點開始走,到達第二個島的第一個城市或第二個城市,這兩個不能算作一條相同的路……    這是常識,雖然我沒讀明白題目大意!

弄懂了上面的着一些再來看看題,當時沒看懂,找到了UPC魚神的代碼恍然大悟。他是假設,姑且這麼認爲吧,遊客到的是第一個到上的第一個城市,那麼每個島有n個城市,就相當於每個島只能到達過n次,最後又回到1島,其實回不回來都一個樣,因爲這不影響我們做題,只要第一次地點的城市也算上的話,那麼最後把每個島n次機會都用完正好停留在2島或者3島就好了,因爲會起點的路徑是確定的,對數目不會有影響!  又因爲不能有類似於迴文串之類的路徑,所有我們只能除以2,迴文串是城市迴文串不是島嶼迴文串…… 
那樣的話不符合正常人理解範圍,雖然我從題目中沒有讀到這樣的描述……

參考代碼:
用c++實現,其中高精度沒有給出代碼,幫助理解還是不錯的!

下面這份是python ,說是做大數毫無壓力


自己會實現的代碼:java版本:
dp[i][j][k][a]表示三個島到達過的城市數量爲分別爲:i ,  j,  k。   a表示目前在哪個島上。
狀態轉移的要求是,不能自己到自己島上的城市,超過n次的話不用管,因爲代碼是從0往上DP的,頂多越界一下而已……
初始化和組合之間的乘加關係自己慢慢體會吧
import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main4 {
   
	static int N=33;
	static BigInteger big1=BigInteger.ONE;
	static BigInteger big0=BigInteger.ZERO;
	static BigInteger big2=BigInteger.valueOf(2);
    static BigInteger dp[][][][]=new BigInteger[N][N][N][3];
    static int n,k;
    public static void main(String[] args) throws IOException  {
        Scanner sc = new Scanner(System.in);
         
        
        	
        	 n = sc.nextInt(); 
        	 init(n);
        	 System.out.println((dp[n][n][n][1].add(dp[n][n][n][2])).divide(big2));
         
    }
   static void init(int  n){
	   
	   for(int i=0;i<=32;++i){
		   for(int j=0;j<=32;++j){
			   for(int k=0;k<=32;++k){
				   for(int t=0;t<3;++t){
					   dp[i][j][k][t]=big0;
				   }
			   }
		   }
	   }
	   dp[1][0][0][0]=big1;
	   for(int i=1;i<=n;++i){
		   for(int j=0;j<=n;++j){
			   for(int k=0;k<=n;++k){
				   for(int t=0;t<3;++t){
					  if(t==0){
						  dp[i][j+1][k][1]= dp[i][j+1][k][1].add(  dp[i][j][k][t].multiply(BigInteger.valueOf(n-j)) );
						  dp[i][j][k+1][2]= dp[i][j][k+1][2].add(  dp[i][j][k][t].multiply(BigInteger.valueOf(n-k)) );
					  }else if(t==1){
						  dp[i+1][j][k][0]= dp[i+1][j][k][0].add(  dp[i][j][k][t].multiply(BigInteger.valueOf(n-i)) );
						  dp[i][j][k+1][2]= dp[i][j][k+1][2].add(  dp[i][j][k][t].multiply(BigInteger.valueOf(n-k)) );
					  }else if(t==2){
						  dp[i+1][j][k][0]= dp[i+1][j][k][0].add(  dp[i][j][k][t].multiply(BigInteger.valueOf(n-i)) );
						  dp[i][j+1][k][1]= dp[i][j+1][k][1].add(  dp[i][j][k][t].multiply(BigInteger.valueOf(n-j)) );
					  }
				   }
			   }
		   }
	   }
	   
	   
   }
}



timus   1172. Ship Routes   URAL 解題報告
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章