Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 4687|回复: 21

[已解决]a和b猜拳,谁先胜3局就获胜,有几种情形?

[复制链接]
发表于 2016-9-13 10:50 | 显示全部楼层 |阅读模式
a a a
a a b a
a a b b a
a a b b b
a b a a
a b a b a
a b a b b
a b b a
a b b a a
a b b a b
a b b b
以上是首局a胜的分支,首局b胜的分支同理。
所以,结果=10*2=20种



请问:如何打印出这20种?谢谢!
最佳答案
2016-9-14 12:53
本帖最后由 香川群子 于 2016-9-14 12:57 编辑

同理,原题目中ab2人比赛的递归部分改成这样更简洁:
  1. Dim k, n
  2. Sub test()
  3.     [a1].CurrentRegion = ""
  4.     n = 3  '2人之间比赛、谁先得到3胜即赢下这一局。
  5.     k = 0: Call dg("", 0, 0, 0)
  6. End Sub

  7. Sub dg(s, a, b, t)
  8.     If a = n Or b = n Then k = k + 1: Cells(k, 1) = s: Cells(k, 2) = t: Exit Sub
  9.     Call dg(s & "a", a + 1, b, t + 1)
  10.     Call dg(s & "b", a, b + 1, t + 1)
  11. End Sub
复制代码


显然递归中不需使用循环,更简单更好。






excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
发表于 2016-9-13 14:50 | 显示全部楼层
本帖最后由 爱疯 于 2020-1-17 14:41 编辑
  1. static void Main(string[] args)
  2.         {
  3.             List<string> list = new List<string> { "a", "a", "a", "b", "b", "b" };
  4.             dTest = new Dictionary<string, string>();
  5.             GroupString(list, "");
  6.             foreach (var d in dTest)
  7.             {
  8.                 string str = d.ToString();
  9.                 int x = 0;
  10.                 int y = 0;
  11.                 string temp = "";
  12.                 foreach (char t in str)
  13.                 {
  14.                     if (t == 'a')
  15.                     {
  16.                         temp += "a";
  17.                         x++;
  18.                     }
  19.                     else if (t == 'b')
  20.                     {
  21.                         temp += "b";
  22.                         y++;
  23.                     }
  24.                     if (x == 3 || y == 3)
  25.                     {
  26.                         Console.WriteLine(temp);
  27.                         break;
  28.                     }
  29.                 }
  30.             }
  31.             Console.ReadKey();
  32.         }

  33.         private static Dictionary<string, string> dTest;
  34.         private static void GroupString(List<string> list, string str)
  35.         {
  36.             for (int i = 0; i < list.Count; i++)
  37.             {
  38.                 List<string> list1 = new List<string>();
  39.                 list1.AddRange(list);
  40.                 string strNew = str + list1[i];
  41.                 list1.RemoveAt(i);
  42.                 string strLast = "";
  43.                 if (list1.Count == 1)
  44.                 {
  45.                     strLast = strNew + list1[0];
  46.                 }
  47.                 else
  48.                 {
  49.                     GroupString(list1, strNew);
  50.                 }

  51.                 if (!dTest.ContainsKey(strLast) && strLast != "")
  52.                 {
  53.                     dTest[strLast] = "";
  54.                 }
  55.             }

  56.         }
复制代码

评分

参与人数 1 +20 金币 +20 收起 理由
爱疯 + 20 + 20 很给力

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2016-9-13 15:13 | 显示全部楼层
小新De和尚头 发表于 2016-9-13 14:50

谢谢 小新De和尚头

我不懂这个语言,是C吗?{:251:}

可否用文字简单的讲解下思路,以便理解和学习 。。。



回复

使用道具 举报

发表于 2016-9-13 15:29 | 显示全部楼层
爱疯 发表于 2016-9-13 15:13
谢谢 小新De和尚头!

我不懂这个语言,是C吗?

思路可能不是最好的,但是结果应该是对的。
思路就是将6个字符存入一个数组里面
然后从数组中按顺序抽去出来,抽过的位置不再重复抽去
比如,假设有数组 [A,B,C,D,E,F]
第一次从第一位抽,得到 A
数组剩余部分[B,C,D,E,F]
在剩余部分再从第一位抽得到 B
数组剩余部分[C,D,E,F]
再从剩余部分从第一位抽 得到 C
...
...
...
然后依次把抽取出来的字符组合成字符串就成了:ABCDEF
再轮回,从数组[A,B,C,D,E,F]中,从第二位开始抽取。得到B
剩余部分[A,C,D,E,F]
在剩余部分从第一位抽:得到A
...
...
...
最后得到字符串BACDEF
..
..
..
这样就可以组合列出所有的排列组合
通过字典把重复项去掉(对于[a,a,a,b,b,b]数组需要去除重复项)
然后再判断每一项是否已经达到 3个a 或者3个b。


回复

使用道具 举报

发表于 2016-9-13 15:30 | 显示全部楼层
爱疯 发表于 2016-9-13 15:13
谢谢 小新De和尚头!

我不懂这个语言,是C吗?

实际就是一个排列组合的问题,
将所有的可能都排列出来,
处理其中符合胜出条件的部分字符串输出即可。
回复

使用道具 举报

 楼主| 发表于 2016-9-13 15:35 | 显示全部楼层
Sub test()
    Dim i, j, s, x
    For i = 111 To 22222
        x = Replace(i, 1, "")
        x = Replace(x, 2, "")
        '如果只含1或2
        If Len(x) = 0 Then
            '如果有3个1且1在末位,或有3个2且2在末位
            If UBound(Split(i, 1)) = 3 And Right(i, 1) = 1 Or UBound(Split(i, 2)) = 3 And Right(i, 1) = 2 Then
                s = s & i & vbCr
                j = j + 1
            End If
        End If
    Next i
    MsgBox s, , j
End Sub



这个没通用性,


不知这么理解对不对:
1)本题中,比如"ab"和"ba",因为是不同的情形,即与顺序有关,所以是排列问题。
2)用"排列组合的通用写法"(唉,还是不会,下去再看。。。),求出3个a和3个b的所有排列。
3)从中去除不符合题意的排列。
回复

使用道具 举报

发表于 2016-9-13 15:45 | 显示全部楼层
爱疯 发表于 2016-9-13 15:35
Sub test()
    Dim i, j, s, x
    For i = 111 To 22222

{:1312:}{:1312:}{:1312:}{:1312:}{:1312:}{:1312:}
回复

使用道具 举报

 楼主| 发表于 2016-9-13 18:01 | 显示全部楼层
小新De和尚头 发表于 2016-9-13 15:45

因为我想学习"排列组合的通用方法",所以问这个。
并不为解决实际的问题,只想来学习。


'生成自然数序列 0000-9999
'http://www.excelpx.com/thread-290190-2-1.html 14楼
Sub GetSeqArrOutput()
    Dim i&, j%, k%, n%, A()
    n = 4
    ReDim A%(10 ^ n - 1, 1 To n)
    For i = 0 To 10 ^ n - 2
        For j = n To 1 Step -1
            If A(i, j) < 9 Then
                '1)处理下一行
                A(i + 1, j) = A(i, j) + 1    '下一行的末位,相对本行的末位,自增1
                For k = 1 To j - 1    '下一行的其它位,相对本行的其它位,值不变
                    A(i + 1, k) = A(i, k)
                Next
                '2)继续外循环
                Exit For
            Else
                '3)当末位进位时,末位重置为0。即其它位最大值不会超过9
                A(i + 1, j) = 0
            End If
        Next j
    Next i
    [a1].Resize(10 ^ n, n) = A
End Sub


Sub test()
    Dim i, j
    For i = 0 To 9
        For j = 0 To 9
            Debug.Print i, j
        Next j
    Next i
End Sub



现在有点理解这个了,对自己来说,要去想出这种方法,感觉 ..... 好别扭。



回复

使用道具 举报

发表于 2016-9-14 08:19 | 显示全部楼层
感觉这个用递归做应该很容易。
回复

使用道具 举报

发表于 2016-9-14 08:33 | 显示全部楼层
超级简单:
  1. Dim k, n
  2. Sub test()
  3.     [a1].CurrentRegion = ""
  4.     n = 3 '设置为先胜3局者胜,即5局3胜制。如n=4则为7局4胜制
  5.     k = 0: Call dg("", 0, 0, 0)
  6. End Sub
  7. Sub dg(s, a, b, t)
  8.     If a = n Or b = n Then k = k + 1: Cells(k, 1) = s: Cells(k, 2) = t: Exit Sub
  9.     For i = 0 To 1
  10.         If i Then Call dg(s & "a", a + 1, b, t + 1) Else Call dg(s & "b", a, b + 1, t + 1)
  11.     Next
  12. End Sub
复制代码



评分

参与人数 2 +26 金币 +20 收起 理由
爱疯 + 20 + 20 很给力
today0427 + 6 学习了!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-4-24 18:13 , Processed in 1.062361 second(s), 13 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表