POJ 1202 Family 概率,DP,高精 难度:2

http://poj.org/problem?id=1202

难度集中在输出格式上,因为输出格式所以是高精度

递推式:

血缘肯定只有从双亲传到儿子的,所以,设f,m为双亲,son为儿子,
p[i][j]为i和j之间的血缘关系,p[j][i]=p[i][j]

则:

p[son][f]=p[son][m]=0.5+0.5*p[f][m]

对于兄弟和其他不是双亲的节点j,则有

p[son][j]=0.5*(p[f][j]+p[m][j])

另外:http://swerc.up.pt/2002/Data/有数据

代码交了好几次都是RE,突然交了一次居然AC了

import java.math.BigDecimal;
import java.util.*;

class mes{
	int son,nxt;
	mes(){son=nxt=0;}
}
public class Main {
	final static int maxn=650;
	static int head[];
	static BigDecimal p[][];
	static mes s[];
	static int fa[][];
	static int n,k,m;
	static int vis[];
	static int que[];

	static void addedge(int f,int t,int ind)
	{
	    s[ind].nxt=head[f];
	    s[ind].son=t;
	    head[f]=ind;
	}
	static Scanner scanner;
	static void init()
	{
		for(int i=0;i<maxn;i++){
			head[i]=-1;
		}
		scanner = new Scanner(System.in);
		n=scanner.nextInt();
		k=scanner.nextInt();
		for(int i=0; i<k; i++)
		{
			int son,f,m;
			son=scanner.nextInt();
			f=scanner.nextInt();
			m=scanner.nextInt();
			addedge(f,son,2*i);
        	addedge(m,son,2*i+1);
        	fa[son][0]=f;
        	fa[son][1]=m;
		}
		for(int i=1; i<=n; i++)
		{
			p[i][i]=BigDecimal.ONE;
		}
	}

	static void calc()
	{
		int front=0,tail=0;
		final BigDecimal mul=BigDecimal.valueOf(0.5);
		for(int i=1; i<=n; i++)
		{
			if(fa[i][0]==0&&fa[i][1]==0&&vis[i]==0)
			{
        	   que[tail++]=i;
        	   vis[i]=1;
			}
		}
		while(tail!=front)
		{
			int tp=que[front];front++;
			vis[tp]=2;
			int f=fa[tp][0],m=fa[tp][1];
			if(f!=0&&m!=0)
			{
				p[tp][f]=p[tp][m]=p[f][tp]=p[m][tp]=(p[f][m].add(BigDecimal.ONE)).multiply(mul);
				for(int i=1; i<=n; i++)
				{
					if(i!=f&&i!=tp&&i!=m)
					{
						p[i][tp]=p[i][tp].add((p[i][m].add(p[i][f])).multiply(mul));
						p[tp][i]=p[i][tp];
					}
				}
			}

			for(int sp=head[tp]; sp!=-1; sp=s[sp].nxt)
			{
				int son=s[sp].son;
				if(vis[son]!=0)continue;
				if(vis[fa[son][0]]==2&&vis[fa[son][1]]==2)
				{
		        	que[tail++]=son;
					vis[son]=1;
				}
			}
		}
	}
	static void show()
	{
		m=scanner.nextInt();
		for(int i=0; i<m; i++)
		{
			int f,t;
			f=scanner.nextInt();
			t=scanner.nextInt();
			String ans = p[t][f].multiply(BigDecimal.valueOf(100)).toPlainString();
			if(ans.indexOf(".")>0&&ans.indexOf(".")<ans.length()){
				while(ans.length()>1&&ans.endsWith("0")){
					ans=ans.substring(0,ans.length()-1);
				}
			}
			if(ans.endsWith(".")&&ans.length()>1)ans=ans.substring(0,ans.length()-1);
			System.out.println(ans+"%");
		}
	}
	public static void main(String[] args) {
		head=new int[maxn];
		p=new BigDecimal[maxn][maxn];
		s=new mes[2*maxn];
		fa=new int[maxn][2];
		que=new int[maxn];
		vis = new int[maxn];
		for(int i=0;i<maxn;i++){p[i]=new BigDecimal[maxn];s[i]=new mes();fa[i]=new int[2];}
		for(int i=0;i<maxn;i++){for(int j=0;j<maxn;j++){p[i][j]=BigDecimal.ZERO;}}
		init();
		calc();
		show();
	}
}
时间: 2024-11-05 11:46:21

POJ 1202 Family 概率,DP,高精 难度:2的相关文章

[ACM] POJ 3071 Football (概率DP)

Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2875   Accepted: 1462 Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, -, 2n. In each round of the tournament, all teams still in the

hdu 4870 Rating(概率DP&amp;高数消元)

Rating Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 714    Accepted Submission(s): 452 Special Judge Problem Description A little girl loves programming competition very much. Recently, she

【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素

POJ 3071-Football(概率dp)

Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3145   Accepted: 1591 Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, -, 2n. In each round of the tournament, all teams still in the

poj 1322 Chocolate (概率dp)

///有c种不同颜色的巧克力,一个个的取,当发现有相同的颜色的就吃掉,去了n个后,到最后还剩m个的概率 ///dp[i][j]表示取了i个还剩j个的概率 ///当m+n为奇时,概率为0 # include <stdio.h> # include <algorithm> # include <string.h> # include <iostream> using namespace std; double dp[1010][1010]; int main()

poj 3071 简单概率dp

题意很清晰,就是问最有可能获得冠军的队伍. 需要注意的是每轮比赛中,每个队都是和自己旁边的一个队比赛,采用淘汰赛制,所以需要决定第i轮的时候j队可以和哪些队比赛,然后求概率dp即可. 状态转移方程: dp[i][j] += dp[i - 1][j] * dp[i - 1][k] * p[j][k]; dp[i][j]表示第i轮j队获胜的概率 = 第i-1轮j队获胜的概率 * 第i-1轮k队获胜的概率 * j队打败k队的概率(之和). 前提是j和k在第i轮可能遇到. 判断方法: ( j >> (

POJ 3156 - Interconnect (概率DP+hash)

题意:给一个图,有些点之间已经连边,现在给每对点之间加边的概率是相同的,问使得整个图连通,加边条数的期望是多少. 此题可以用概率DP+并查集+hash来做. 用dp(i,j,k...)表示当前的每个联通分量的点数分别是i,j,k...(连通分量的个数不固定)时,加边的期望. 这样以dp(i,j,k)为例分析状态转移的过程,dp(i,j,k)=p1*dp(i,j,k)+p2*dp(i+j,k)+p3*dp(i,j+k)+p4*dp(j,i+k)+1. 终止条件是dp(n)=0,因为此时图一定联通,

[DP][高精][NOIP]Hanoi双塔问题

题目梗概 Hanoi塔问题的基础上,每种圆盘加了一个.实际内容并没有变化. 思考 首先来一波Hanoi问题的步数公式推导: 首先n个不同的圆盘. 只有把n-1个圆盘从a->b,最后把a上剩余的一个圆盘从a->c. 之后把b上的n-1个圆盘从b->c. 这里的两步:把n-1个圆盘从a->c,和n-1个圆盘从b->c.所需要的步骤数.实际上就是把n-1个圆盘从a移动到c的步骤数*2,因为是等价的.从a->b和从b->c移动的圆盘个数都是一样的,所以步数就是 (n-1)

BZOJ5300 [Cqoi2018]九连环 【dp + 高精】

题目链接 BZOJ5300 题解 这题真的是很丧病,,卡高精卡到哭 我们设\(f[i]\)表示卸掉前\(i\)个环需要的步数 那么 \[f[i] = 2*f[i - 2] + f[i - 1] + 1\] 直接高精递推不仅\(MLE\)而且\(TLE\) 然后就要用到数学求通项公式,或者打表找规律 \[f[n] = \lfloor \frac{2^(n + 1)}{3} \rfloor\] 高精乘低精就可以过了 #include<algorithm> #include<iostream&