ZOJ 3605Find the Marble(dp)
大体意思就是 找出随机选了K个交换后 石子在第i个罐子里的概率最大
也就是可能的总数最大 这样就可以写出递推方程 dp[i][j][k] += dp[i-1][e][k]; (0<e<j&& k!=a[j]&&k!=b[j]) dp[i][j][a[j]]+=dp[i-1][e][b[j]] dp[i][j][b[j]]+=dp[i-1][e][a[j]];
dp[i][j][k]表示选第i次交换时 选的为第j个 而且石子在第K个罐子里的可能 这样有两种可能 1:石子在a[j]或b[j]中 也就是要交换的两个罐头里 那么可能数就交换相加,然后再加别的。
要么是不在 那么就加上上一步的可能总数 。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 LL dp[55][55][55],sum[55]; 18 int a[55],b[55]; 19 int main() 20 { 21 int s,g,e,t,i,j,k,n,m; 22 cin>>t; 23 while(t--) 24 { 25 cin>>n>>m>>k>>s; 26 memset(dp,0,sizeof(dp)); 27 memset(sum,0,sizeof(sum)); 28 for(i =1; i <= m ;i++) 29 { 30 cin>>a[i]>>b[i]; 31 if(a[i]==s) 32 dp[1][i][b[i]] = 1; 33 else if(b[i]==s) 34 dp[1][i][a[i]] = 1; 35 else 36 dp[1][i][s] = 1; 37 } 38 for(i = 2 ; i<= k ;i++) 39 for(j = i; j <= m ;j++) 40 { 41 for(e = i-1 ; e < j; e++) 42 { 43 if(a[j]!=b[j]) 44 { 45 dp[i][j][a[j]]+=dp[i-1][e][b[j]]; 46 dp[i][j][b[j]]+=dp[i-1][e][a[j]]; 47 } 48 else 49 dp[i][j][a[j]] += dp[i-1][e][a[j]]; 50 for(g = 1; g <= n ;g++) 51 { 52 if(g==a[j]) continue; 53 if(g==b[j]) continue; 54 dp[i][j][g]+=dp[i-1][e][g]; 55 } 56 } 57 } 58 LL maxz=0; 59 int ans = s; 60 for(i = k; i <= m ; i++) 61 { 62 for(j = 1; j <= n ; j++) 63 { 64 sum[j]+=dp[k][i][j]; 65 } 66 } 67 for(i = 1; i <= n ;i++) 68 { 69 if(maxz<sum[i]) 70 { 71 ans = i; 72 maxz = sum[i]; 73 } 74 } 75 cout<<ans<<endl; 76 } 77 return 0; 78 }