project euler 121

Disc game prize fund

A bag contains one red disc and one blue disc. In a game of chance a player takes a disc at random and its colour is noted. After each turn the disc is returned to the bag, an extra red disc is added, and another disc is taken at random.

The player pays £1 to play and wins if they have taken more blue discs than red discs at the end of the game.

If the game is played for four turns, the probability of a player winning is exactly 11/120, and so the maximum prize fund the banker should allocate for winning in this game would be £10 before they would expect to incur a loss. Note that any payout will be a whole number of pounds and also includes the original £1 paid to play the game, so in the example given the player actually wins £9.

Find the maximum prize fund that should be allocated to a single game in which fifteen turns are played.


碟子游戏奖金

一开始,包里装有一个红色碟子和一个蓝色碟子。在一场概率游戏中,每一轮玩家从包中取出一个碟子,记录下其颜色,随后将碟子放回包中,并在包中加入一个红色碟子,再进行下一轮。

玩家需要付£1来玩这个游戏,如果他们在游戏结束时拿出的蓝色碟子数比红色碟子数更多,则获得胜利。

如果游戏进行4轮,那么玩家获胜的概率是11/120,因此游戏所设定的最高奖金为£10,否则可能会造成亏损。注意奖金必须是整数,而且包含了玩家付出用于玩游戏的£1,也就是说玩家实际上赢得的数额是£9。

如果游戏进行15轮,求游戏所设定的最高奖金。

package projecteuler;

import junit.framework.TestCase;

public class Prj121 extends TestCase {

	public void testDiscGamePrizeFund() {

		RationalNum[][] prob = new RationalNum[15 + 1][15 + 2];

		prob[3][0] = new RationalNum(1 * 2 * 3, 2 * 3 * 4);
		prob[3][1] = new RationalNum(1 * 2 * 3, 2 * 3 * 4).add(
				new RationalNum(1 * 1 * 3, 2 * 3 * 4)).add(
				new RationalNum(1 * 2 * 1, 2 * 3 * 4));

		prob[3][2] = new RationalNum(1 * 1 * 1, 2 * 3 * 4).add(
				new RationalNum(1 * 2 * 1, 2 * 3 * 4)).add(
				new RationalNum(1 * 1 * 3, 2 * 3 * 4));

		prob[3][3] = new RationalNum(1 * 1 * 1, 2 * 3 * 4);

		for (int i = 4; i <= 15; i++) {

			RationalNum win = new RationalNum(1, i + 1);
			RationalNum lost = new RationalNum(i, i + 1);

			for (int j = 0; j <= i; j++) {

				prob[i][j] = new RationalNum();
				if (j == i) {
					prob[i - 1][j] = new RationalNum(0, win.down);
				}

				System.out.println("i=" + i + ",j=" + j);
				prob[i][j] = prob[i - 1][j].multiply(lost);

				if (j != 0) {
					prob[i][j] = prob[i][j].add(prob[i - 1][j - 1]
							.multiply(win));
				}

			}

		}

		RationalNum r = new RationalNum();
		for (int i = 15; i <= 15; i++) {
			for (int j = i; 2 * j > i; j--) {
				r = r.add(prob[i][j]);
			}
		}

		System.out.println(r);
		System.out.println(Math.floor(r.down / r.up));

	}

	public static class RationalNum {
		public long up;
		public long down;

		public RationalNum(long up, long down) {
			super();
			this.up = up;
			this.down = down;
		}

		public RationalNum() {
			this(0, 1);
		}

		public RationalNum multiply(RationalNum num) {
			return new RationalNum(num.up * up, num.down * down);
		}

		public RationalNum add(RationalNum num) {

			if (up == 0) {
				return num;
			} else if (num.up == 0) {
				return this;
			}
			if (num.down == down) {
				return new RationalNum(up + num.up, down);
			}
			return new RationalNum(up * num.down + down * num.down, num.down
					* down);
		}

		@Override
		public String toString() {
			return "RationalNum [up=" + up + ", down=" + down + "]";
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值