您的位置:首页 > 其它

ZOJ 3605 Find the Marble

2013-04-05 10:55 393 查看
传说中的江湖赌骗术,能自己想到的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];
else
dp[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: