結果

問題 No.309 シャイな人たち (1)
ユーザー kura07kura07
提出日時 2015-12-03 23:54:12
言語 Ruby
(3.3.0)
結果
TLE  
実行時間 -
コード長 2,572 bytes
コンパイル時間 297 ms
コンパイル使用メモリ 11,380 KB
実行使用メモリ 24,052 KB
最終ジャッジ日時 2023-10-12 09:37:13
合計ジャッジ時間 10,761 ms
ジャッジサーバーID
(参考情報)
judge11 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 TLE -
testcase_01 -- -
testcase_02 -- -
testcase_03 -- -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
権限があれば一括ダウンロードができます
コンパイルメッセージ
Syntax OK

ソースコード

diff #

# 求める期待値
expectation_value = 0

class Person
	attr_accessor :p, :s
	def to_s
		"(p=#@p, s=#@s)"
	end
end

# seats に person を格納する。
# person には p(倉敷市が何県の都市か知っている確率)、s(シャイ度) を入れておく
def get_data
	seats = []
	r, c = gets.split.map(&:to_i)
	r.times{ seats.push Array.new(c){ Person.new } }
	gets
	r.times{|i|
		seats[i].zip(gets.split.map(&:to_f)).each{|person,p| person.p = p/100 }
	}
	gets
	r.times{|i|
		seats[i].zip(gets.split.map(&:to_i)).each{|person,s| person.s = s }
	}
	return [seats, r, c]
end
seats, num_rows, num_cols = get_data

# 手を挙げる人を求める
def who_raise(row, bit_knows, prev_bit_raises=0)
	bit_raises = 0
	num_raise = 0
	points = row.each_with_index.map{|p,i| bit_knows[i]==1 ? 4-p.s : 0 }
	row.size.times{|i| points[i] += prev_bit_raises[i] } if prev_bit_raises != 0
	changed = true
	while changed
		changed = false
		points.size.times{|i|
			if points[i] >= 4
				points[i-1] += 1 if i-1 >= 0
				points[i+1] += 1 if i+1 < points.size
				points[i] = 0
				bit_raises |= 1 << i
				num_raise += 1
				changed = true
			end
		}
	end
	return [bit_raises, num_raise]
end

# 最前列から順に処理していく
# raise_probabilities は、ひとつ前の列における全て挙手の組み合わせの確率を格納する
prev_raise_probabilities = []
raise_probabilities = []
num_rows.times{|r|
	row = seats[r]
	# 最前列の場合、ひとつ前の列が全くあげていないのと同じことである
	if r == 0
		prev_raise_probabilities = Array.new(2**num_cols, 0.0)
		prev_raise_probabilities[0] = 1
	end
	# 一列のそれぞれの人が知っているかどうかの組み合わせで処理を行う
	# 左からi人目が知っていれば bit_knows[i]==1、知らなければ bit_knows[i]==0
	raise_probabilities = Array.new(1<<num_cols, 0.0)
	prev_raise_probabilities.each_with_index.select{|p,b| p!=0 }.each{
		|prev_raise_probability,prev_bit_raises|
		(1<<num_cols).times{|bit_knows|
			probability = prev_raise_probability
			# bit_knows の組み合わせになる確率を計算する
			row.each_with_index{|p,i| probability *= bit_knows[i]==1 ? p.p : 1-p.p }
			# 手を挙げる人を求める
			bit_raises, num_raise = who_raise(row, bit_knows, prev_bit_raises)
			# 挙手の組み合わせの確率に加算する
			raise_probabilities[bit_raises] += probability
			# 期待値に加算する
			expectation_value += num_raise * probability
		}
		prev_raise_probabilities = raise_probabilities
	}
}

puts expectation_value
0