ZOJ 3605Find the Marble

来源:互联网 发布:cms监控软件使用说明 编辑:程序博客网 时间:2024/06/05 04:28

传说中的江湖赌骗术,能自己想到的dp都不是什么复杂的dp。用dp[i][j]k]表示前i次交换看漏j次最后猜k的可能排列数,递推时,若第i步看漏,则dp[i][j][k] += dp[i-1][j-1][k]。若第i步没看漏,则分两种情况:第i步的交换与k有关,另外一个是l,则dp[i][j][k] += dp[i-1][j][l];若无关,则dp[i][j][k] += dp[i-1][j][k]。最后在dp[m][m-k]中找最大值输出下标即可。

但是数组要用long long或者double,另外有可能m=k=0,所以初值应是dp[0][0][s] = 1。


#include <stdio.h>#include <memory.h>int n, m, k, s;long long dp[51][51][51];int from[51], to[51];inline int leadto(int s, int i){if(s == from[i]) return to[i];if(s == to[i]) return from[i];else return 0;}int main(){int N, i, j, temp, maxi;long long max, *a;scanf("%d", &N);while(N --){scanf("%d%d%d%d", &n, &m, &k, &s);for(i=1; i<=m; ++i)scanf("%d%d", &from[i], &to[i]);memset(dp, 0, sizeof(dp));dp[0][0][s] = 1;for(i=1; i<=m; ++i){for(j=1; j<=n; ++j){temp = leadto(j, i);for(s=0; s<=i; ++s){if(s != 0)dp[i][s][j] += dp[i-1][s-1][j];if(temp != 0)dp[i][s][j] += dp[i-1][s][temp];elsedp[i][s][j] += dp[i-1][s][j];}}}max = -1, a = dp[m][m-k];for(i=1; i<=n; ++i){if(a[i] > max){max = a[i];maxi = i;}}printf("%d\n", maxi);}return 0;}


原创粉丝点击