找回密码
 欢迎注册
楼主: 056254628

[求助] 一种策略游戏

[复制链接]
发表于 2012-4-12 12:02:37 | 显示全部楼层
规则规定归零的手关闭(既不予取,也不许入)是必要的,否则游戏不会有胜负。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-12 13:03:25 | 显示全部楼层

局面的合并与过滤

本帖最后由 hujunhua 于 2012-4-13 07:13 编辑 一个局面 M 完整的表达可用$((a,b),(c,d))$, 其中(a,b), (c,d)都是无序对。定义$M*k:=((a*k, b*k),(c*k, d*k))$, *是四则运算符。 合并法则:M×k等价于M,当gcd(k,N)=1时。 过滤法则:若从$((1,1),(1,1))$开始博弈,那么M×k可以从全体局面集中滤掉,当gcd(k,N)>1。 1~9中任意意都可以乘以适当的k变成1,2,5之一,所以不妨让a限于1,2,5而b,c,d取1~9中适当的值。 如此一来,7#的内容可以简化为:当两人手中都有一数归零(mod10)后,就只有16种局面,而且不存在策略了。这16种局面不难划分出胜负和。红色为先胜局面(7个),黑色为先负局面(6个):{11} → {12} → {23} → {15} →{52} →{27} → {17} → {14} → {25} → {51} → {16} → {29} →{19} {10}, 判和的局面共3个,形成一个循环{1, 3} → {1, 8} → {2, 1} → {1,3}
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-4-12 16:16:41 | 显示全部楼层
我觉得程序不能判断胜负和的局面应该也是构成循环,因此也是属于和的局面。 这样的话大部分局面都属于和。1111也是其中的一个。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-12 21:48:45 | 显示全部楼层
我觉得程序不能判断胜负和的局面应该也是构成循环,因此也是属于和的局面。 这样的话大部分局面都属于和。1111也是其中的一个。 056254628 发表于 2012-4-12 16:16
楼主这话是否暗示有非循环和局?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-4-12 23:49:34 | 显示全部楼层
14# hujunhua 误会我的意思了。 我的程序是这样的。 f(a,b,c,d)的值表示胜负和。 (a<=b,c<=d) 0 表示负,1表示和,2表示胜。 x表示未知,可能是0,可能是1,也可能是2. 其中f(0,b,0,d)值,已经知道,分别是0、1、2. 对于其他的f(a,b,c,d)初始都是x 接着对所有的a、b、c、d运行以下程序: (a,b,c,d)有四种变化,(a、c中有1个0,变化减少2个。) (a1,b1,a,b),(a2,b2,a,b),(a3,b3,a,b),(a4,b4,a,b) 我的表示法是先手的数字放后面 具体判断如下: 这四种局面的f值中: *如果没有x,那么f(a,b,c,d)=2-min(f(a1,b1,a,b),f(a2,b2,a,b),f(a3,b3,a,b),f(a4,b4,a,b)) *如果有x,那么只要有一个0,f(a,b,c,d)=2 *有x,没有0,那么 f(a,b,c,d)=x (即f值没有变化) ------------------------------------------------------------------------- 这样,对所有的a、b、c、d每循环上述程序一次,f值等于x的局面个数就会减少。 一直到f值等于x的局面个数不变为止。 按照我的设想,所有的局面最后都会归结于(0,b,0,d)局面,f值等于x的局面个数最后归0,这样所有的局面都有最终的结果,或胜或负或和。 但实际上不是如此,f值等于x的局面个数最后稳定在2000以上。 所以我才说大多数局面无法得到确切的结果。 想想原因可能是这样的:f(a,b,c,d)的值取决于其他局面的值,其他局面的值取决于......,最后又取决于前面出现过的局面的值,这样就形成了循环,双方为了不形成必胜局面给对方,谁都不愿意从循环局面中离开,所以这些局面都是和局。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-4-13 00:13:27 | 显示全部楼层
对于f(a,b,c,d)=2-min(f(a1,b1,a,b),f(a2,b2,a,b),f(a3,b3,a,b),f(a4,b4,a,b)) f(a1,b1,a,b),f(a2,b2,a,b),f(a3,b3,a,b),f(a4,b4,a,b)中有x,没0的情况: 可以简化,把所有值为2的删除,最后剩下的都是值为1,或x。 选择值为1的变化,就保证和局,选择为x的变化,比如f(a1,b1,a,b)=x, 那么一直选择值为x的变化,如(a,b,c,d) -->(a1,b1,a,b) -->(a2,b2,a1,b1)-->(a3,b3,a2,b2)-->...... 最后陷入循环之中(这个循序是费脑力的,必须时刻保持正确的选择,否则会输),或者在中间的某个局面选择值为1的变化,最后归于双方只有一个数字的和局循环之中(这个循环不需用脑,没得选择)。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-13 07:38:12 | 显示全部楼层
算法很妙,但是初值很重要。仅限于f(0,b,0,d)不够。f(a,b,0,d)=2,当a+d=0(mod10)或者b+d=0(mod10)时,它下一步终止于f(0,0,a,b)而不是f(0,b,o,d)型初值。 这个算法很容易实现递归程序,但递归层次会不会太深,尤其是对局面数不作合并与过滤的情况下。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-13 07:49:17 | 显示全部楼层
  1. // sf.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include <map>
  5. #include <vector>
  6. #include <list>
  7. #include <algorithm>
  8. using namespace std;
  9. #define MOD 10
  10. unsigned char mullist[3]={3,7,9};
  11. #define MC (sizeof(mullist)/sizeof(mullist[0]))
  12. //we must make sure a<=b and c<=d
  13. #define MAKE_STATE(a,b,c,d) ((((unsigned)(unsigned char)a)<<24)|(((unsigned)(unsigned char)b)<<16)|(((unsigned)(unsigned char)c)<<8)|(((unsigned)(unsigned char)d)))
  14. #define GET_A(x) ((unsigned char)(((unsigned)(x))>>24))
  15. #define GET_B(x) ((unsigned char)(((unsigned)(x))>>16))
  16. #define GET_C(x) ((unsigned char)(((unsigned)(x))>>8))
  17. #define GET_D(x) ((unsigned char)(((unsigned)(x))))
  18. unsigned int make_state(unsigned char a, unsigned char b, unsigned char c, unsigned char d)
  19. {
  20. unsigned char t;
  21. if(a>b){t=b;b=a;a=t;}
  22. if(c>d){t=d;d=c;c=t;}
  23. return MAKE_STATE(a,b,c,d);
  24. }
  25. typedef map<unsigned int, int> IdMap;
  26. IdMap myIdMap;
  27. vector<unsigned int> idToState;
  28. vector<unsigned int> result;
  29. #define UNKNOWN 0
  30. #define FIRSTWIN 1
  31. #define FIRSTLOST 2
  32. struct Edges{
  33. int e[4];
  34. };
  35. vector<Edges> prev,next;
  36. list<int> losers;
  37. vector<int> winers;
  38. int lc,wc;
  39. int getStateId(unsigned int x)
  40. {
  41. IdMap::iterator it;
  42. it=myIdMap.find(x);
  43. if(it==myIdMap.end())return -1;
  44. return it->second;
  45. }
  46. void init()
  47. {
  48. unsigned char a,b,c,d;
  49. int id=0;
  50. int i;
  51. myIdMap.clear();
  52. for(a=0;a<MOD;a++)for(b=a;b<MOD;b++)for(c=0;c<MOD;c++)for(d=c;d<MOD;d++){
  53. unsigned int state = make_state(a,b,c,d);
  54. int i;
  55. for(i=0;i<MC;i++){
  56. IdMap::iterator iit=myIdMap.find(make_state((a*mullist[i])%MOD,(b*mullist[i])%MOD,(c*mullist[i])%MOD, (d*mullist[i])%MOD));
  57. if(iit!=myIdMap.end()){
  58. myIdMap.insert(make_pair(state,iit->second));
  59. break;
  60. }
  61. }
  62. if(i==MC){
  63. myIdMap.insert(make_pair(state,id));
  64. idToState.push_back(state);
  65. id++;
  66. }else{
  67. continue;
  68. }
  69. }
  70. for(i=0;i<id;i++)result.push_back(UNKNOWN);
  71. for(id=0;id<idToState.size();++id){
  72. unsigned int state=idToState[id];
  73. unsigned char a,b,c,d;
  74. a=GET_A(state);
  75. b=GET_B(state);
  76. c=GET_C(state);
  77. d=GET_D(state);
  78. if(c==0&&d==0){
  79. Edges e;
  80. e.e[0]=e.e[1]=e.e[2]=e.e[3]=-1;
  81. next.push_back(e);
  82. continue;///terminate states, no out edges
  83. }
  84. int cc=0;
  85. int j;
  86. Edges e;
  87. if(c!=0){
  88. if(a!=0)
  89. e.e[cc++]=myIdMap.find(make_state(c,d,(a+c)%MOD,b))->second;
  90. if(b!=0)
  91. e.e[cc++]=myIdMap.find(make_state(c,d,a,(b+c)%MOD))->second;
  92. }
  93. if(d!=0){
  94. if(a!=0)
  95. e.e[cc++]=myIdMap.find(make_state(c,d,(a+d)%MOD,b))->second;
  96. if(b!=0)
  97. e.e[cc++]=myIdMap.find(make_state(c,d,a,(b+d)%MOD))->second;
  98. }
  99. sort(&e.e[0],&e.e[cc]);
  100. for(i=1,j=1;i<cc;i++){
  101. if(e.e[i]==e.e[i-1])continue;
  102. e.e[j]=e.e[i];
  103. j++;
  104. }
  105. cc=j;
  106. for(i=cc;i<4;i++){
  107. e.e[i]=-1;///mark invalid edges
  108. }
  109. next.push_back(e);
  110. }
  111. for(id=0;id<idToState.size();++id){
  112. unsigned int state=idToState[id];
  113. unsigned char a,b,c,d;
  114. a=GET_A(state);
  115. b=GET_B(state);
  116. c=GET_C(state);
  117. d=GET_D(state);
  118. if(a==0&&b==0){
  119. Edges e;
  120. e.e[0]=e.e[1]=e.e[2]=e.e[3]=-1;
  121. prev.push_back(e);
  122. continue;
  123. }
  124. int cc=0;
  125. int j;
  126. Edges e;
  127. if(a!=0){
  128. if((c-a)%MOD!=0)
  129. e.e[cc++]=myIdMap.find(make_state((c-a+MOD)%MOD,d,a,b))->second;
  130. if((d-a)%MOD!=0)
  131. e.e[cc++]=myIdMap.find(make_state(c,(d-a+MOD)%MOD,a,b))->second;
  132. }
  133. if(b!=0){
  134. if((c-b)%MOD!=0)
  135. e.e[cc++]=myIdMap.find(make_state((c-b+MOD)%MOD,d,a,b))->second;
  136. if((d-b)%MOD!=0)
  137. e.e[cc++]=myIdMap.find(make_state(c,(d-b+MOD)%MOD,a,b))->second;
  138. }
  139. sort(&e.e[0],&e.e[cc]);
  140. for(i=1,j=1;i<cc;i++){
  141. if(e.e[i]==e.e[i-1])continue;
  142. e.e[j]=e.e[i];
  143. j++;
  144. }
  145. cc=j;
  146. for(i=cc;i<4;i++){
  147. e.e[i]=-1;///mark invalid edges
  148. }
  149. prev.push_back(e);
  150. }
  151. for(id=0;id<idToState.size();++id){
  152. unsigned int state=idToState[id];
  153. unsigned char a,b,c,d;
  154. a=GET_A(state);
  155. b=GET_B(state);
  156. c=GET_C(state);
  157. d=GET_D(state);
  158. if(c==0&&d==0&&(a!=0||b!=0)){
  159. result[id]=FIRSTLOST;
  160. losers.push_back(id);
  161. lc++;
  162. }
  163. if(a==0&&b==0&&(c!=0||d!=0)){
  164. result[id]=FIRSTWIN;
  165. wc++;
  166. }
  167. }
  168. }
  169. void dumpstate(int i){
  170. unsigned int state=idToState[i];
  171. unsigned char a,b,c,d;
  172. // if(result[i]!=FIRSTLOST)return;
  173. a=GET_A(state);
  174. b=GET_B(state);
  175. c=GET_C(state);
  176. d=GET_D(state);
  177. printf("state[%d:%d;%d:%d] is ",a,b,c,d);
  178. if(result[i]==FIRSTWIN){
  179. printf("first user win\n");
  180. }else if(result[i]==FIRSTLOST){
  181. printf("first user lost\n");
  182. }else{
  183. printf("tie \n");
  184. }
  185. }
  186. int _tmain(int argc, _TCHAR* argv[])
  187. {
  188. int i;
  189. init();
  190. start:
  191. while(losers.size()>0){
  192. int id = losers.front();
  193. losers.pop_front();
  194. for(i=0;i<4;i++){
  195. int pid=prev[id].e[i];
  196. if(pid<0)break;
  197. if(result[pid]==UNKNOWN){
  198. result[pid]=FIRSTWIN;
  199. wc++;
  200. winers.push_back(pid);
  201. }else if(result[pid]!=FIRSTWIN){
  202. fprintf(stderr,"Invalid 1\n");
  203. return -1;
  204. }
  205. }
  206. }
  207. int c=winers.size();
  208. for(i=0;i<c;i++){
  209. int id = winers[i];
  210. int j;
  211. for(j=0;j<4;j++){
  212. int pid=prev[id].e[j];
  213. if(pid<0)break;
  214. if(result[pid]==UNKNOWN){
  215. int k;
  216. for(k=0;k<4;k++){
  217. if(next[pid].e[k]<0)break;
  218. if(result[next[pid].e[k]]!=FIRSTWIN)break;
  219. }
  220. if(k==4||next[pid].e[k]<0){//all next are first_win
  221. result[pid]=FIRSTLOST;
  222. lc++;
  223. losers.push_back(pid);
  224. }
  225. }
  226. }
  227. }
  228. if(losers.size()>0)goto start;
  229. c=result.size();
  230. printf("win count=%d, lost count=%d, undertermined=%d\n",wc,lc,c-wc-lc);
  231. for(i=0;i<result.size();i++){
  232. if(result[i]!=UNKNOWN){
  233. dumpstate(i);
  234. }
  235. }
  236. return 0;
  237. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-4-13 07:50:45 | 显示全部楼层
程序使用了hujunhua的等价类合并方法,所以一个状态可能代表两个或四个等价状态 win count=117, lost count=49, undertermined=607 state[0:0;0:1] is first user win state[0:0;0:2] is first user win state[0:0;0:5] is first user win state[0:0;1:1] is first user win state[0:0;1:2] is first user win state[0:0;1:3] is first user win state[0:0;1:4] is first user win state[0:0;1:5] is first user win state[0:0;1:6] is first user win state[0:0;1:8] is first user win state[0:0;1:9] is first user win state[0:0;2:2] is first user win state[0:0;2:4] is first user win state[0:0;2:5] is first user win state[0:0;2:8] is first user win state[0:0;5:5] is first user win state[0:1;0:0] is first user lost state[0:1;0:1] is first user win state[0:1;0:2] is first user lost state[0:1;0:4] is first user lost state[0:1;0:5] is first user lost state[0:1;0:6] is first user win state[0:1;0:7] is first user win state[0:1;0:9] is first user win state[0:1;1:7] is first user win state[0:1;1:9] is first user win state[0:1;2:2] is first user win state[0:1;2:7] is first user win state[0:1;2:9] is first user win state[0:1;3:3] is first user win state[0:1;3:9] is first user win state[0:1;4:5] is first user win state[0:1;4:6] is first user win state[0:1;4:9] is first user win state[0:1;5:9] is first user win state[0:1;6:6] is first user win state[0:1;6:9] is first user win state[0:1;7:7] is first user lost state[0:1;7:9] is first user win state[0:1;8:9] is first user win state[0:1;9:9] is first user win state[0:2;0:0] is first user lost state[0:2;0:2] is first user win state[0:2;0:3] is first user win state[0:2;0:4] is first user lost state[0:2;0:5] is first user win state[0:2;0:7] is first user lost state[0:2;0:8] is first user win state[0:2;0:9] is first user lost state[0:2;1:7] is first user win state[0:2;1:8] is first user win state[0:2;1:9] is first user win state[0:2;2:2] is first user win state[0:2;2:4] is first user win state[0:2;2:8] is first user win state[0:2;2:9] is first user win state[0:2;3:5] is first user lost state[0:2;3:7] is first user win state[0:2;3:8] is first user win state[0:2;4:4] is first user win state[0:2;4:5] is first user win state[0:2;4:6] is first user win state[0:2;4:8] is first user win state[0:2;4:9] is first user win state[0:2;5:8] is first user win state[0:2;6:6] is first user win state[0:2;6:8] is first user win state[0:2;6:9] is first user win state[0:2;7:8] is first user win state[0:2;7:9] is first user win state[0:2;8:8] is first user win state[0:2;8:9] is first user win state[0:2;9:9] is first user win state[0:5;0:0] is first user lost state[0:5;0:1] is first user lost state[0:5;0:2] is first user win state[0:5;0:5] is first user win state[0:5;1:1] is first user win state[0:5;1:3] is first user win state[0:5;1:4] is first user win state[0:5;1:5] is first user win state[0:5;1:8] is first user win state[0:5;2:5] is first user win state[0:5;5:5] is first user win state[1:1;0:0] is first user lost state[1:1;0:4] is first user win state[1:1;0:6] is first user lost state[1:1;0:8] is first user lost state[1:1;0:9] is first user lost state[1:1;1:9] is first user win state[1:1;6:9] is first user win state[1:1;7:9] is first user win state[1:1;9:9] is first user win state[1:2;0:0] is first user lost state[1:2;0:8] is first user win state[1:2;7:9] is first user win state[1:2;8:8] is first user win state[1:2;9:9] is first user win state[1:3;0:0] is first user lost state[1:3;0:6] is first user lost state[1:3;0:8] is first user lost state[1:3;0:9] is first user lost state[1:3;7:9] is first user win state[1:4;0:0] is first user lost state[1:4;0:6] is first user win state[1:4;0:9] is first user lost state[1:4;2:9] is first user win state[1:4;3:9] is first user win state[1:4;6:9] is first user win state[1:4;7:9] is first user win state[1:4;9:9] is first user win state[1:5;0:0] is first user lost state[1:5;0:2] is first user win state[1:5;0:5] is first user win state[1:5;0:9] is first user win state[1:5;1:9] is first user win state[1:6;0:0] is first user lost state[1:6;0:4] is first user lost state[1:6;0:9] is first user win state[1:6;4:4] is first user win state[1:6;4:9] is first user win state[1:8;0:0] is first user lost state[1:8;0:3] is first user win state[1:8;0:6] is first user lost state[1:8;0:9] is first user win state[1:8;3:9] is first user win state[1:9;0:0] is first user lost state[1:9;0:1] is first user lost state[1:9;0:5] is first user lost state[1:9;1:9] is first user win state[2:2;0:0] is first user lost state[2:2;0:2] is first user lost state[2:2;0:3] is first user lost state[2:2;0:4] is first user lost state[2:2;0:6] is first user lost state[2:2;0:8] is first user lost state[2:2;0:9] is first user lost state[2:2;2:8] is first user win state[2:2;3:8] is first user win state[2:2;5:8] is first user win state[2:2;8:8] is first user win state[2:4;0:0] is first user lost state[2:4;0:4] is first user lost state[2:4;0:6] is first user win state[2:4;2:6] is first user win state[2:4;2:8] is first user win state[2:4;4:6] is first user win state[2:4;6:6] is first user win state[2:4;6:7] is first user win state[2:4;8:8] is first user win state[2:5;0:0] is first user lost state[2:5;0:5] is first user lost state[2:5;0:8] is first user lost state[2:5;2:8] is first user win state[2:5;5:8] is first user win state[2:8;0:0] is first user lost state[2:8;0:2] is first user lost state[2:8;0:4] is first user lost state[2:8;0:5] is first user lost state[2:8;2:2] is first user win state[2:8;2:6] is first user win state[2:8;2:8] is first user win state[5:5;0:0] is first user lost state[5:5;0:5] is first user lost state[5:5;2:5] is first user win state[5:5;5:5] is first user win
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-4-13 11:09:46 | 显示全部楼层

标题

17# hujunhua (0,0,a,b)局面的初值我没有设置,直接在程序里判断,能变化成该局面的f值为2.,当然,把它们设成初值为0也行。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-23 13:01 , Processed in 0.034179 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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