CSU1513 Kick the ball! 湖南10届省赛 dfs

1513: Kick the ball!

时间限制: 1 Sec   内存限制: 128 MB   Special Judge
提交: 166   解决: 102
[ 提交][ 状态][ 讨论版]

题目描述

"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".

输入

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.

输出

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.

样例输入

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

样例输出

Case 1: 6.98%
Case 2: 100.00%
Case 3: 0.00%
Case 4: 0.47%
Case 5: 9.73%

提示

来源

湖南省第十届大学生计算机程序设计竞赛


http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1513


//湖南省赛 结果做了一天 没过

//题意 A B 两只队伍 点球A B 轮流 射5场  

//  前面五个数是A对 进球的概率 

//  如果 两队的 差距 已经通过后面的比赛 挽救 不了  就结束

// 求 一 输入的比分 结束比赛的概率

// 下面两份代码第一份我写的 错的

// 我是把一场比赛 A B 都踢 四种情况

//  思路觉得没错 应该是精度问题  如果提前结束  A OR B 一个T完 一个就不要T了直接记录概率

// 我是 T完 一场 在 判断   可能有精度丢失吧

 //QQ  740773689  找到我的错误 20QB

#include<stdio.h>
#include<algorithm>
using namespace std;
int m,n;
double zp;
double a1[10],a2[10];
double b1[10],b2[10];
void dfs(double pp,int s1,int s2,int k)
{
    if(s1>n||s2>m) return ;
    if(pp<1e-6)  return ;
    if(k==6)
   {
        if(s1==n&&s2==m)
        {
            zp+=pp;
        }
        return ;
    }
        if((abs(s1-s2))>(6-k))
        {
            if(s1==n&&s2==m)
             zp+=pp;
            return ;
        }
     dfs(pp*a1[k]*b2[k],s1+1,s2,k+1);
     dfs(pp*a2[k]*b1[k],s1,s2+1,k+1);
     dfs(pp*a1[k]*b1[k],s1+1,s2+1,k+1);
     dfs(pp*a2[k]*b2[k],s1,s2,k+1);
}

int main()
{
    int T;
    T=1;
    int i;
    while(T<=100)
    {
        for(i=1; i<=5; i++)
        {
            scanf("%lf",&a1[i]);
            a2[i]=1.0-a1[i];
        }
        for(i=1; i<=5; i++)
        {
            scanf("%lf",&b1[i]);
            b2[i]=1.0-b1[i];
        }
        scanf("%d-%d",&n,&m);
        zp=0;
        printf("Case %d: ",T);
        dfs(1.0,0,0,1);
        if(zp==0) printf("0.00%%\n");
        else
        {
            zp*=100;
            printf("%.2lf%%\n",zp);
        }
        T++;
    }
    return 0;
}


 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;
double p[11];
int a, b;
double ans;
int match_continue( int left, int x, int y )//判断比赛是否还需要进行下去
{
    if( x - y - ( left + 1 ) / 2 > 0 ) return 1;//x>y
    if( y - x - left / 2 > 0 ) return 1;//x<y
    return 0;
}
void dfs( int x, int y, int k, double p1 )
{
    if( p1 < 1e-6 ) return;
    if( k == 10 )
    {
        if( x == a && y == b )
            ans+=p1;
        return ;
    }
    if( match_continue(10-k, x, y ) ) //比赛结束直接传值即可
    {
        //dfs( x, y, k+1, p1 );return;
        if( x == a && y == b )
        ans+=p1;
        return;
    }
    if( k % 2 == 0 )
    {
        dfs( x+1, y, k+1, p1*p[k] );//此次踢球进了,比分改变
        dfs( x, y, k+1, p1*(1-p[k]) );//未进,比分不变,比赛继续
    }
    else {
        dfs( x, y+1, k+1, p1*p[k] );
        dfs( x, y, k+1, p1*(1-p[k]) );
    }

}
int main()
{
    int cas = 1;
    while( scanf ( "%lf", &p[0] ) != EOF )
    {
        for( int i = 1; i < 5; i ++ )
            scanf ( "%lf", &p[2*i] );
        for( int i = 0; i < 5; i++ )
        scanf ( "%lf", &p[2*i+1] );
        scanf ( "%d-%d", &a, &b );
        ans = 0;
        dfs( 0, 0, 0, 1.0 );//依次代表a的比分,b的比分,第k次比赛,此时的概率
        printf("Case %d: %.2f%%\n", cas++, 100*ans );
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值