hdu计算机学院大学生程序设计竞赛(2015’11)1003 玩骰子

来源:互联网 发布:仿今日头条网站源码 编辑:程序博客网 时间:2024/05/24 06:49
玩骰子


Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1017    Accepted Submission(s): 306




Problem Description
  Nias与Ains都特别喜欢玩骰子,而且都自以为比对方玩得更溜。
  终于有一天,他们决定用骰子来一决高下!
  一般的骰子玩法已经不足以体现他们的水平了,于是他们自创了一套玩法来PK:
首先,每人掷3个骰子;之后,可以选择其中一个骰子重新掷(当然也可以放弃这一步),最后,比较投掷结果的大小,结果大的那方获胜,一样的话为平局。
  大小比较规则为:
  三个一样数字的骰子称为三条;两个一样数字的骰子称为对子;只有一个数字的骰子成为散牌。三条>对子>散牌。当双方结果都为三条时,直接比较三条数字的大小;都有对子时,先比较对子数字的大小,若相同,再比较剩下的骰子的数字的大小;都只有散牌时,先比较最大的数字的大小,若相同,再比较次大的数字的大小,还相同,最后比较最小的数字的大小。


  现在Nias已经投了3个骰子,还剩一次机会可以选择其中一个骰子重新投(或不选),而且他已经知道了Ains的最后投掷结果,求Nias获胜的概率有多大。
 


Input
输入数据第一行为一个整数T,表示有T组测试数据。
接下来T行,每行6个1~6的整数,前三个表示Nias第一次的投掷结果,后三个表示Aias最终的投掷结果。
 


Output
请输出Nias获胜的概率,结果保留3位小数,每组输出占一行。
 


Sample Input
4
2 3 5 3 3 4
3 3 1 2 2 2
6 2 1 5 4 3
1 2 3 4 4 1
 


Sample Output
0.333
0.167
1.000
0.000

刚开始理解错了,以为是从3个骰子中任取一个然后掷骰子,第一个数据怎么算怎么不对,后来才知道是选定获胜几率最大的,然后掷骰子,求最大的概率,也就是选获胜可能性最大的骰子,掷之,算出其获胜概率。

对Nias的第一个骰子进行从1到6枚举,然后用一个check函数来判断是否获胜,若获胜cou++,最后cou / 6求出Nias掷这个骰子的获胜概率,同样求出第二个,第三个的获胜概率,取最大值作为结果即可。


#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <limits>#include <algorithm>#include<functional>#include <set>using namespace std;int nias[3], ains[3];int size = sizeof(nias);bool check(const int *n, const int *a) {int nt[3], at[3];   //因为也要保持t1的只读性否则枚举每个骰子的时候会出错memcpy(nt, n, size);memcpy(at, a, size);int cou1, cou2;set<int> s1, s2;  //用set来筛,看3个骰子中有几种骰子for (int i = 0; i < 3; i++) {s1.insert(nt[i]);s2.insert(at[i]);}cou1 = s1.size();cou2 = s2.size();if (cou1 < cou2) {  //此时nias和ains中骰子种数分别为:(2,3)或(1,3)或(1,2)nias胜return true;}else if (cou1 == cou2) {   //相等的时候分类讨论都只有1或2或3种时的情况if (cou1 == 1) {if (nt[0] > at[0])  //直接判断其中任意元素大小return true;else return false;}else if (cou1 == 2) {sort(nt, nt + 3); //先排序,排序后肯定0号或者2号元素有且只有一个和1号元素相同的sort(at, at + 3);int tem;if (nt[1] == nt[2]) {  //将相同的元素靠前放tem = nt[2];nt[2] = nt[0];nt[0] = tem;}if (at[1] == at[2]) {tem = at[2];at[2] = at[0];at[0] = tem;}if (nt[0] < at[0]) {   //先比较相同元素即“对子”大小return false;}else if (nt[0] > at[0]) {   //若相同再比较剩下的成单的return true;}else {if (nt[2] > at[2])return true;else return false;  //注意平局时不算赢}}else if (cou1 == 3) {sort(nt, nt + 3, greater<int>());   //降序排列,挨个比较sort(at, at + 3, greater<int>());for (int i = 0; i < 3; i++) {if (nt[i] > at[i])return true;else if (nt[i] < at[i])return false;}return false;  //平局}}else if (cou1 > cou2) {  //此时nias和ains中骰子种数分别为:(3,2)或(3,1)或(2,1)nias负return false;}}double MAX(double a, double b) {if (a > b) {return a;}else {return b;}}int main(){int T;scanf("%d", &T);while (T--) {for (int i = 0; i < 3; i++) {scanf("%d", &nias[i]);}for (int i = 0; i < 3; i++) {scanf("%d", &ains[i]);}if (check(nias, ains)) {  //若刚开始就获胜则直接输出1.000printf("1.000\n");continue;}//t1用来临时存放nias,t2用来临时存放ains,因为中间要对数组进行改变,要一直保持nias和ains的只读性//cou用来记录获胜次数int t1[3], t2[3], cou;double maxn = -1;for (int i = 0; i < 3; i++) {memcpy(t1, nias, size);memcpy(t2, ains, size);cou = 0;for (t1[i] = 1; t1[i] <= 6; t1[i]++) {  //枚举每个骰子if (check(t1, t2)) {cou++;}}maxn = MAX(maxn, 1.0 * cou / 6);  //不断取大值}printf("%.3f\n", maxn);}return 0;}




0 0
原创粉丝点击