Kick the ball!
Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%lld & %llu
Description
"A penalty shoot-out (officially kicks from the penalty mark) is a method of determining the winner of an association football (soccer) match that is drawn after the regulation playing time and any applicable extra time periods have been played. In a penalty shoot-out, each team takes turns attempting a specified number of shots from the penalty mark (usually 5) that are only defended by the opposing team's goalkeeper, with the team scoring the most goals being declared the winner."
-- wikipedia
The game finally comes to the shoot-out. What will the final result be? "1-3!" You took a wild guess. But what is the probability that your guess is correct?
In this problem, team A kicks first (which is determined by a coin toss, as usual), both teams will attempt at most 5 shots (after all the 10 shots, the game may end in draw again), but the game will end as soon as the winner is already determined. For example, after the first 8 kicks the score is 3-2 (left side is team A’s score, right side is team B), then if the 9-th kick is a goal, the game will end immediately with score 4-2, because even team B got its last kick, it still loses for sure. Another example: if all the first 9 kicks are goals, the last kick (from team B) will still be performed, because although team B cannot win, the result might be a "draw", which is better than "lose".
Input
There will be at most 100 test cases. Each case contains two lines. The first line contains 10 floating numbers. The first 5 numbers are the goal probability of the players in team A (player 1 will shoot first, etc), the next 5 numbers are the goal probabilities of the players in team B. Each probability will have exactly one digit after the decimal point. The second line contains your guess, in the format of scoreA-scoreB. 0<=scoreA,scoreB<=5.
Output
For each test case, print the case number and the probability (in percentage) that your wild guess is correct, to 2 decimal places. An absolute error of 0.01% will be ignored.
Sample Input
0.4 0.7 0.7 0.6 0.5 0.8 0.9 0.7 0.2 0.8
1-3
1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0
2-0
1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0
2-0
0.4 0.7 0.7 0.6 0.5 0.8 0.9 0.7 0.2 0.8
5-5
0.4 0.7 0.7 0.6 0.5 0.8 0.9 0.7 0.2 0.8
4-2
Sample Output
Case 1: 6.98%
Case 2: 100.00%
Case 3: 0.00%
Case 4: 0.47%
Case 5: 9.73%
2014年湖南省第十届程序设计竞赛的题目
题意:A、B两队共十人轮流点球,给出每个球员进球的概率,然后输出出现"x-y"比分的概率。
用dfs暴搜即可,我写了两个dfs模拟。注意当已经确定某个队可以获胜时就不用再继续踢下去。比如,踢到第九个球时,A进球3,B进球1,则第十个球B不用再踢,即便第十个球进了也是3-2,B输定了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int n = 5;
int cnt1, cnt2;
double pi;
double a[5], b[5];
void b_dfs(int apos, int bpos, double p, int ka, int kb);
void a_dfs(int apos, int bpos, double p, int ka, int kb) //A踢
{
if (ka > cnt1 || kb > cnt2 || apos > n || bpos > n)
return;
if (n - apos < kb - ka || n - bpos < ka - kb || (apos == n && bpos == n))
{
if (ka == cnt1 && kb == cnt2)
pi += p;
return;
}
b_dfs(apos + 1, bpos, p * (1 - a[apos]), ka, kb); //A进球,B踢
b_dfs(apos + 1, bpos, p * a[apos], ka + 1, kb); //未进,B踢
}
void b_dfs(int apos, int bpos, double p, int ka, int kb) //B踢球
{
if (ka > cnt1 || kb > cnt2 || apos > n || bpos > n)
return;
if (n - bpos < ka - kb || n - apos < kb - ka || (apos == n && bpos == n))
{
if (ka == cnt1 && kb == cnt2)
pi += p;
return;
}
a_dfs(apos, bpos + 1, p * (1 - b[bpos]), ka, kb);
a_dfs(apos, bpos + 1, p * b[bpos], ka, kb + 1);
}
int main()
{
int test = 1;
char c;
while (~scanf("%lf", &a[0]))
{
for (int i = 1; i < n; ++i)
scanf("%lf", &a[i]);
for (int i = 0; i < n; ++i)
scanf("%lf", &b[i]);
scanf("%d%c%d", &cnt1, &c, &cnt2);
pi = 0;
a_dfs(0,0,1,0,0);
printf("Case %d: %.2f%%\n", test++, 100 * pi);
}
return 0;
}