fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define _T_ 0 /* 天:Top */
  6. #define _B_ 1 /* 地:Bottom */
  7. #define _E_ 2 /* 東:East */
  8. #define _W_ 3 /* 西:West */
  9. #define _S_ 4 /* 南:South */
  10. #define _N_ 5 /* 北:North */
  11.  
  12. // サイコロの値の保持
  13. typedef struct {
  14. long x,y,z;
  15. int topside;
  16. int d[6];
  17. } die_t;
  18.  
  19. // 1行入力
  20. int input(int *n, int *tn, int *fn)
  21. {
  22. // 入力が 0 なら 0 を返す
  23. // 入力が 1文字 なら 1 を返す
  24. // 入力が 3文字 なら 2 を返す
  25. char s[4];
  26. char s2[4];
  27. int x,y;
  28. gets(s);
  29. sscanf(s,"%d",&x);
  30. sprintf(s2,"%d",x);
  31. if(strlen(s2) == strlen(s))
  32. {
  33. if(0 == x)
  34. {
  35. return 0;
  36. }
  37. else
  38. {
  39. *n = x;
  40. return 1;
  41. }
  42. }
  43. y = s[2] - '0';
  44. *tn = x;
  45. *fn = y;
  46. return 2;
  47. }
  48.  
  49. // 指定座標にサイコロが存在するか確認する
  50. int exist(long x, long y, long z, int n, die_t *dice)
  51. {
  52. int i;
  53. for(i=0;i<n;i++)
  54. {
  55. if(
  56. (dice[i].x == x) &&
  57. (dice[i].y == y) &&
  58. (dice[i].z == z))
  59. {
  60. return 1;
  61. }
  62. }
  63. return 0;
  64. }
  65.  
  66.  
  67. int roll(die_t *dice, int i, int n)
  68. {
  69. int is_roll = 0;
  70. int j,k,e,e2;
  71. long x,y,z,stop;
  72. int *d; // サイコロの目、d = {天,地,東,西,南,北} ※東西南北の北から見ている想定
  73. int _e[6]; // サイコロの目の大きい順に方向をソート
  74. int _x[] = {0,0,1,-1,0,0};
  75. int _y[] = {0,0,0,0,1,-1};
  76.  
  77. x = dice[i].x;
  78. y = dice[i].y;
  79. z = dice[i].z;
  80. d = dice[i].d;
  81.  
  82. stop = z; // Z=0では転がることができない!
  83. // 転がす
  84. while(stop){
  85. // 方角ソート
  86. for(j=0;j<6;j++)
  87. {
  88. for(k=0;k<6;k++)
  89. {
  90. if(d[k] == j+1)
  91. {
  92. _e[j] = k;
  93. }
  94. }
  95. }
  96. // 4~6の方向へ転がれるなら転がる。
  97. for(j=5;j>2;j--)
  98. {
  99. e = _e[j]; // 面の方向(0天,1地,2東,3西,4南,5北)
  100. if(e>1) // 3~6の面が天・地でない。
  101. {
  102. if(!exist(x+_x[e], y+_y[e], z-1, i, dice)) // 4~6の面がある方向にサイコロが無く、転がることができる場合。
  103. {
  104. // 転がる。座標処理
  105. x += _x[e];
  106. y += _y[e];
  107. z--;
  108. // 転がる。出目処理
  109. e2 = (e%2==0)?e+1:e-1; // eの反対面
  110. k = d[e];
  111. d[e] = d[_T_];
  112. d[_T_] = d[e2];
  113. d[e2] = d[_B_];
  114. d[_B_] = k;
  115. // 転がり探し、止め。
  116. j = 0;
  117. // 回転フラグ
  118. is_roll = 1;
  119. }
  120. }
  121. }
  122. stop = (0==j)? z:0; // 終了判定
  123. }
  124. dice[i].topside = d[_T_];
  125. dice[i].x = x;
  126. dice[i].y = y;
  127. dice[i].z = z;
  128. return is_roll;
  129. }
  130.  
  131. // 上面と前面のサイコロの目から、サイコロのデータを登録する。
  132. void setDice(die_t *die, int ti, int fi)
  133. {
  134. int wi;
  135. int w[6][6]={ // 西方の目を天と北から得る。WEST = w[TOP][NORTH]
  136. {0,3,5,2,4,0},
  137. {4,0,1,6,0,3},
  138. {2,6,0,0,1,5},
  139. {5,1,0,0,6,2},
  140. {3,0,6,1,0,4},
  141. {0,6,2,5,3,0}
  142. };
  143. // サイコロの目の設定
  144. wi = w[ti-1][fi-1];
  145. die->d[_T_] = ti; die->d[_B_] = 7-ti;
  146. die->d[_N_] = fi; die->d[_S_] = 7-fi;
  147. die->d[_W_] = wi; die->d[_E_] = 7-wi;
  148. }
  149.  
  150. // 主となる処理
  151. char* main_proc(int n, int *t, int *f)
  152. {
  153. int i,j;
  154. int ti; // 現在処理の対象としているサイコロにおけるtop,west,front(north)の目
  155. long x,y,z; // 座標
  156. int loop; // 繰り返しroll処理が必要か。
  157. // サイコロのデータ。
  158. die_t *dice;
  159. // 最終結果の格納変数
  160. char* s_res;
  161. int result[6] = {0,0,0,0,0,0};
  162.  
  163. // サイコロのデータの領域割当。
  164. dice = (die_t *)calloc(n ,sizeof(die_t));
  165. // 落として転がす処理 //
  166. for(i=0;i<n;i++)
  167. {
  168. setDice(&dice[i], t[i], f[i]);
  169.  
  170. // 落とす。
  171. x = 0; y = 0; z = 0;
  172. while(exist(x,y,z,i,dice)) z++;
  173. dice[i].x = x;
  174. dice[i].y = y;
  175. dice[i].z = z;
  176. dice[i].topside = t[i];
  177.  
  178. // 転がす。
  179. loop = roll(dice, i, i);
  180. while(loop)
  181. {
  182. loop = 0;
  183. for(j=0;j<i+1;j++) loop = (roll(dice,j,i+1))?1:loop;
  184. }
  185. }
  186. // 表示 //
  187. for(i=0;i<n;i++)
  188. {
  189. x = dice[i].x;
  190. y = dice[i].y;
  191. z = dice[i].z;
  192. ti = dice[i].topside;
  193. if(!exist(x,y,z+1,n,dice)) result[ti-1]++;
  194. }
  195. // 文字列化
  196. s_res = (char*)calloc(255,sizeof(char));
  197. sprintf(s_res,"%d %d %d %d %d %d\n",result[0],result[1],result[2],result[3],result[4],result[5]);
  198. s_res = (char*)realloc(s_res,sizeof(char)*(strlen(s_res)+1));
  199. free(dice);
  200. return s_res;
  201. }
  202.  
  203. int main(void)
  204. {
  205. int i;
  206. int n, *t, *f;
  207. int nn, tn, fn;
  208. int ret;
  209. char *results;
  210. char *rtmp;
  211. int results_len;
  212.  
  213. results = (char*)calloc(1,sizeof(char));
  214.  
  215. // 入力
  216. ret = input(&nn, &tn, &fn);
  217. while(ret==1)
  218. {
  219. n = nn; // 入力されるサイコロの個数
  220. // 入力データの領域割当
  221. t = (int *)calloc(n ,sizeof(int));
  222. f = (int *)calloc(n ,sizeof(int));
  223. // サイコロデータ入力
  224. for(i=0;i<n;i++)
  225. {
  226. if(2 != input(&nn, &tn, &fn)){
  227. return 1;
  228. }
  229. t[i] = tn;
  230. f[i] = fn;
  231. }
  232. // 主処理
  233. rtmp = main_proc(n, t, f);
  234. // 回答文字列連結
  235. results_len = strlen(results);
  236. results = (char*)realloc(results, sizeof(char)*(results_len+strlen(rtmp)+1));
  237. strcpy(results+results_len, rtmp);
  238. free(rtmp);
  239. // 入力データ破棄
  240. free(t);
  241. free(f);
  242. // 入力
  243. ret = input(&nn, &tn, &fn);
  244. }
  245. //最終出力
  246. printf("%s", results);
  247. free(results);
  248. return 0;
  249. }
  250.  
Success #stdin #stdout 0s 1928KB
stdin
4
6 4
6 4
6 4
6 4
2
5 3
5 3
8
4 2
4 2
4 2
4 2
4 2
4 2
4 2
4 2
6
4 6
1 5
2 3
5 3
2 4
4 2
0
stdout
0 1 1 0 0 1
1 0 0 0 1 0
1 2 2 1 0 0
2 3 0 0 0 0