トピックリンク:LightOJ - 1030
説明
あなたは、洞窟の中で長い洞窟です!洞窟は、で表すことができる\(1 \回N \)グリッド。洞窟の各セルは金の任意の量を含むことができます。
最初は、あなたが位置にある\(1 \) 。今、各あなたは完璧なスローターン(6 \)\を面ダイス。あなたが取得する場合、\(X \)投げた後にサイコロで、追加\(X \)に自分の位置を、新しい位置からすべての金を集めます。あなたの新しい位置が洞窟の外にある場合は、適切な結果を得るまで、その後は再び投げ続けます。あなたが到達すると、\(N ^ {番目} \)の位置を、あなたの旅を停止します。今、あなたは洞窟についての情報を与えている、あなたは見つけるために持っていると予想しますが、特定の手順を使用して収集することができます金の数を。
入力
入力は、整数で始まり\(T(100≤)\)テストケースの数を表します。
それぞれの場合は空白行と整数含ま\(N(1≤N≤100)\)洞窟の寸法を示すが。次の行は含まれてい\(N \)のスペースで区切られた整数を。\(^ I {番目} \)この行の整数は、あなたがに来る場合、あなたが取得する金の量表し\(^ I {番目} \)の細胞を。あなたは安全に与えられた全ての整数が負になることを仮定してもよいし、何の整数がより大きくなりません\(\ 1000) 。
出力
それぞれのケースについて、ケース番号とあなたが収集する金の予想数を印刷します。より少ないエラー\(10 ^は、{ - 6} \)は無視されます。
サンプル入力
3
1
101
2
10 3
3
3 6 9
サンプル出力
Case 1: 101.0000000000
Case 2: 13.000
Case 3: 15
解決
問題の意味
そこ\(N \)グリッドは、各グリッド値は\(ヴァル[I] \)金の、最初のあなたの最初のグリッド。
すべてのスロー(6 \)\数に投げ込まサイコロ顔、\(X_Iは\) 、前方に行きます\(X_I \)を超える場合には、グリッド、グリッドを\(N \) 、再度キャスト、行きます格子\(N \)が終わりました。金の期待の値を取得するために探しています。
考え
あなたは使用することができる確率DPまたはDPが期待解決します。
確率DP
各グリッドの確率に達し、その後、ラインに一緒に疲れた各グリッドの値を乗じて計算しました。
セット\(DP [I] \)格子の\(Iは\)確率、\(DP [iがjは+]ルJ DPを= [iがjは+] + DP [I] / Kの\(1 \ \ Kル、\ K =分(6、N-- I))\) 。
DP期待
セット\(DP [I] \)格子の\(Iは\)する\(N \)は、所望の金を得ることができ、\(DP [N]はヴァルを= [N] \) 。
状態遷移方程式である\(DP [I] = \ FRAC。1 {{}} K \ sum_。1} ^ {KDP J = [IがJを+] \(K =分(6、N-- I))\) 。
コード
確率DP
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int v[maxn];
double dp[maxn];
int main() {
int T;
scanf("%d", &T);
int kase = 0;
while(T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &v[i]);
}
memset(dp, 0, sizeof(dp));
dp[1] = 1.0;
for(int i = 1; i <= n; ++i) {
int k = min(6, n - i);
for(int j = 1; j <= k; ++j) {
dp[i + j] += dp[i] * 1.0 / k;
}
}
double ans = 0.0;
for(int i = 1; i <= n; ++i) {
ans += dp[i] * v[i];
}
printf("Case %d: %.7lf\n", ++kase, ans);
}
return 0;
}
DP期待
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int v[maxn];
double dp[maxn];
int main() {
int T;
scanf("%d", &T);
int kase = 0;
while(T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &v[i]);
}
memset(dp, 0, sizeof(dp));
dp[n] = v[n];
for(int i = n - 1; i >= 1; --i) {
dp[i] = v[i];
int k = min(6, n - i);
for(int j = 1; j <= k; ++j) {
dp[i] += dp[i + j] * 1.0 / k;
}
}
printf("Case %d: %.7lf\n", ++kase, dp[1]);
}
return 0;
}