• CodeForces 398B 概率DP 记忆化搜索


    题目:http://codeforces.com/contest/398/problem/B


    有点似曾相识的感觉,记忆中上次那个跟这个相似的 我是用了 暴力搜索过掉的,今天这个肯定不行了,dp方程想了非常久也没有想出来,有点无从下手的感觉,最后还是尝试了一下记忆化搜索,以dp[0][0]为边界,dp[x][y]代表当前有x行y列没有彩色的 瓷砖,搜索起来思路还是非常清晰的,可惜最后那个 算期望公式给写错了,瞎了好久,做出以后看了一下别人的做法,确实有点难想到,把涂好的都放在右下角,这样就仅仅有四种情况了,瓷砖移动肯定是有影响的,后来理解了他们那意思是 划分西线把瓷砖划分到右下角去,这样 状态转移 事实上跟记忆化搜索的一模一样了,想不到那个转移,


    int n,m;
    
    int xx[20000 + 55],yy[20000 + 55];
    
    double dp[2000 + 55][2000 + 55];
    
    int cntx = 0,cnty = 0;
    
    void init() {
    	memset(xx,0,sizeof(xx));
    	memset(yy,0,sizeof(yy));
    	memset(dp,-1,sizeof(dp));
    }
    
    bool input() {
    	while(cin>>n>>m) {
    		cntx = cnty = n;
    		for(int i=0;i<m;i++) {
    			int x,y;
    			scanf("%d %d",&x,&y);
    			if(!xx[x])cntx--;
    			if(!yy[y])cnty--;
    			xx[x]++;
    			yy[y]++;
    		}
    		return false;
    	}
    	return true;
    }
    
    double dfs(int nowx,int nowy) {
    	if(dp[nowx][nowy] > -1.0 + eps)return dp[nowx][nowy];
    	if(nowx == 0 && nowy == 0)return dp[nowx][nowy] = 0.00;
    	double p = nowx * 1.0/n;
    	double q = nowy * 1.0/n;
    	double ans = 1.00;
    	if(nowx != 0)ans += dfs(nowx - 1,nowy) * p * (1.0 - q);
    	if(nowy != 0) ans += dfs(nowx,nowy - 1) * (1.0 - p) * q;
    	if(nowx != 0 && nowy != 0)ans += dfs(nowx - 1,nowy - 1) * p * q;
    	return dp[nowx][nowy] = ans/(1.00 - (1.0 - p) * (1.0 - q));
    }
    
    void cal() {
    	double ans = dfs(cntx,cnty);
    	printf("%.10lf
    ",ans);
    }
    
    void output() {
    
    }
    
    int main() {
    	while(true) {
    		init();
    		if(input())return 0;
    		cal();
    		output();
    	}
    	return 0;
    }


  • 相关阅读:
    Linux命令格式及7个常见终端命令
    Linux主要目录速查表
    Linux和Windows系统目录结构区别
    C语言下进制的使用
    C语言变量和常量
    C语言的关键字和数据类型
    Linux下交换文件说明
    gcc编译过程
    C语言图形界面QT和MFC(待学)
    字符编码问题
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4504464.html
Copyright © 2020-2023  润新知