[bzoj1419]Red is good 题解

[bzoj1419]Red is good 题解

我真的是服了,没想到被一个 不能四舍五入 给坑惨了。

推导

因为指派是线性排放,很容易想到线性DP。设 dpi,j 表示取了 i 个红牌,j 个黑牌的期望。

对于 dpi,j,很容易想到有两种:

  • 上一个拿了一个红牌:值为 dpi1,j+1,概率为 ii+j​。
  • 上一个拿了一个黑牌:值为 dpi,j11,概率为 ji+j

所以推导公式为:

dpi,j=(dpi1,j+1)×ii+j+(dpi,j11)×ji+j

因为是在最优情况下,所以当 dpi,j<0 时,令 dpi,j=0

下面开始头疼的环节:如何不四舍五入?其实并不难,但是被精度卡就很难受。

代码放上,祥建注释:

void print(double printion) {
	long long fixing = printion * 1000000 * 10; // 1000000取出后6位,再×10取出判断四舍五入的一位(注意开long long,卡了我30min)
	fixing = (fixing - fixing % 10) / 10; // 删去判断四舍五入的一位
	double ans = fixing * 1.0 / 1000000; // 直接除就可以了
	printf("%.6lf", ans); // printf
}

举个例子:41.666666666...

  • 四舍五入:41.666667

  • 我的输出:41.666666

第一步,fixing = 416666666

第二步,fixing = (416666666 - 416666666 % 10) / 10 = 41666666

第三步,ans = 41666666 * 1.0 / 1000000 = 41.666666

代码

#include <bits/stdc++.h>
#define Maxn 5005

using namespace std;

int n, m; // n -- Red;m -- Black
double dp[3][Maxn];

void print(double printion) {
	long long fixing = printion * 1000000 * 10;
	fixing = (fixing - fixing % 10) / 10;
	double ans = fixing * 1.0 / 1000000;
	printf("%.6lf", ans);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	cin >> n >> m;
	
	for (int i = 1; i <= n; i ++) {
		dp[1][0] = i;
		for (int j = 1; j <= m; j ++) {
			dp[1][j] = (dp[0][j] + 1) * i * 1.0 / (i + j) + (dp[1][j - 1] - 1) * j * 1.0 / (i + j);
			if (dp[1][j] < 0.0) { dp[1][j] = 0.0; }
		} for (int j = 1; j <= m; j ++) {
			dp[0][j] = dp[1][j];
		}
	}
	
//	print(41.66666666666);
	print(dp[1][m]);
	return 0;
}

由于内存只有 64MB,我还用了一个 轮换数组(自己编的名字),就是将两行轮换使用,节省内存。

posted @   BLM-dolphin  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示