Advertisement
Guest User

Untitled

a guest
Jan 22nd, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.71 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. /*==============================================
  6. (NANMAI)大富豪が選ぶ枚数を制御しています
  7. 任意の整数(N以下じゃないとバグる)を指定すれば大富豪はその枚数で選びます
  8. M_rand(N)を指定すればランダムな値が毎回出力されずにバグります
  9. ==============================================*/
  10. //#define NANMAI 1500
  11.  
  12. /*==============================================
  13. (SEED) 乱数のシード値です
  14. 1を指定すれば毎回同じ額面が出現します
  15. time()を指定すればいつも違った値が出ずにバグります
  16. ==============================================*/
  17. //#define SEED 1
  18.  
  19. //関数のプロトタイプ宣言
  20. int *gen_data(int n, int seed, int mode, float r);
  21. long choose_check(int *a, int N, int M);
  22. int M_rand(int N);
  23. void QSort(int x[ ], int left, int right);
  24. void Swap(int x[ ], int i, int j);
  25. long Search(int x[], int n, long Target);
  26.  
  27. int main(void){
  28. clock_t start,end; //時間測定:はじめと終わりの時間を記憶します
  29. int *a; //小切手の額面を記憶する配列のヤツ
  30. int N; //小切手の枚数
  31. int M; //大富豪が選ぶ枚数
  32. long Target;
  33. int SEED; //乱数のシード
  34.  
  35. //seed値を毎回変更する
  36. srand((unsigned int)time(NULL));
  37.  
  38. //いらん代入だけどチェック用
  39. SEED = rand();
  40.  
  41. //プレイヤーが好きな数Nを大富豪に対して宣言する
  42. //printf("input N:");
  43. //scanf("%d",&N);
  44.  
  45. for(N=1000000; N<5000000001; N=N+1000000){
  46. //N枚の小切手を作成
  47. a = gen_data(N,SEED,1,0.0); //SEEDは#define参照。
  48.  
  49. //大富豪が選ぶ枚数を乱数により決定する
  50. M = 1 + (int)(rand()*(N-1.0+1.0)/(1.0+RAND_MAX));
  51.  
  52. //seedが乱数になってるかチェック
  53. //printf("SEED=%d M=%d a[0]=%d\n",SEED,M,a[0]);
  54.  
  55. //大富豪が金額を選ぶ
  56. Target = choose_check(a,N,M);
  57. //printf("Target:%ld yen.\n",Target);
  58.  
  59. //時間の測定を開始
  60. start = clock();
  61.  
  62. //##################################
  63. //#######ここから組み合わせを選ぶ#######
  64. //##################################
  65.  
  66. QSort(a, 0, N-1);
  67.  
  68. int i, j=1;
  69. for(i=j;i<N;i++){ //大きい数から順にガンガン引く
  70. if(a[N-i] <= Target){
  71. //printf("Answer: %d\n",a[N-i]);
  72. Target = Target-(long)a[N-i];
  73. }else{
  74. break;
  75. }
  76. }
  77. for(j=i;a[N-j] > Target;j++); //次に引ける数を探す
  78.  
  79. if(Target!=0) Target = Search(a, N-j, Target);
  80.  
  81. if(Target==0) //printf("Success!\n")
  82.  
  83. //printf("%ld\n",Target);
  84.  
  85. //選ばれた額面の表示
  86.  
  87.  
  88. //##################################
  89. //#######ここまで組み合わせを選ぶ#######
  90. //##################################
  91.  
  92. //時間の測定を終了
  93. end = clock();
  94.  
  95. //時間の測定結果を出力
  96. printf("%d:%f\n",N,(double)(end-start)/CLOCKS_PER_SEC);
  97.  
  98. //額面データを破棄
  99. free(a);
  100. }
  101.  
  102.  
  103. }
  104.  
  105. int *gen_data(int n, int seed, int mode, float r)
  106. {
  107. //r1_sort.hの流用 => 乱数の範囲を指定できるように工夫
  108. //mode 1 しか実用的でない
  109. int i;
  110. int *data;
  111.  
  112. data = (int *)malloc(sizeof(int) * n); // 配列用のメモリ確保
  113.  
  114. switch(mode) {
  115.  
  116. case 1: // 全て乱数を格納
  117. for (i=0; i<n; i++) {
  118. data[i] = 1 + (int)rand()*(1000000.0-1.0+1.0)/(1.0+RAND_MAX);
  119. }
  120. break;
  121.  
  122. case 2: // 部分ソート済みデータを格納(非実装)
  123. if (r<0 || r>1) {
  124. printf("error: in gen_data(), 'r' should be set between 0 and 1.¥n");
  125. exit(1);
  126. }
  127. for (i=0; i<(int)(n*r); i++) {
  128. data[i] = i;
  129. }
  130. for (i=(int)(n*r); i<n; i++) {
  131. data[i] = rand();
  132. }
  133. break;
  134.  
  135. case 3: // 逆順ソート済みデータを格納(非実装)
  136. for (i=0; i<n; i++) {
  137. data[i] = n-i;
  138. }
  139. break;
  140.  
  141. default: // その他
  142. printf("error: in gen_data(), 'mode' should be set between 1 and 3.¥n");
  143. exit(1);
  144. }
  145.  
  146. return data;
  147. }
  148.  
  149. long choose_check(int *a,int N,int M){
  150. // *a :無作為に選んだ金額を記憶する配列
  151. // N :aの配列の長さ
  152. // M :大富豪が選ぶ枚数
  153. long sum=0;//大富豪が選んだ小切手の金額の合計
  154.  
  155. //seed値を変えます
  156. srand(time(NULL));
  157.  
  158. //少し手間取るが...
  159. int *b;
  160. b = (int *)malloc(sizeof(int)*N); //メモリを確保して
  161.  
  162. for(int i=0; i<N; i++){
  163. b[i] = i;
  164. }
  165.  
  166. //Fisher_Yates
  167. for(int i=0; i<N; i++){
  168. int j = rand()%N;
  169. int t = b[i];
  170. b[i] = b[j];
  171. b[j] = t;
  172. }
  173.  
  174. for(int i=0; i<M; i++){
  175. // printf("chosen(%d):%7d\n",i,a[b[i]]);
  176. sum += (long)a[b[i]];
  177. }
  178. free(b);
  179. return sum;
  180. }
  181.  
  182.  
  183. int M_rand(int N){
  184. int M = 1 + (int) rand()*(N-1.0+1.0)/(1.0+RAND_MAX);
  185. return M;
  186. }
  187.  
  188. void QSort(int x[ ], int left, int right)
  189. {
  190. int i, j;
  191. int pivot;
  192.  
  193. i = left; // ソートする配列の一番小さい要素の添字
  194. j = right; // ソートする配列の一番大きい要素の添字
  195.  
  196. pivot = x[(left + right) / 2]; // 基準値を配列の中央付近にとる
  197.  
  198. while (1) { // 無限ループ
  199.  
  200. while (x[i] < pivot) // pivot より大きい値が
  201. i++; // 出るまで i を増加させる
  202.  
  203. while (pivot < x[j]) // pivot より小さい値が
  204. j--; // 出るまで j を減少させる
  205. if (i >= j) // i >= j なら
  206. break; // 無限ループから抜ける
  207.  
  208. Swap(x, i, j); // x[i] と x[j]を交換
  209. i++; // 次のデータ
  210. j--;
  211. }
  212. if (left < i - 1) // 基準値の左に 2 以上要素があれば
  213. QSort(x, left, i - 1); // 左の配列を Q ソートする
  214. if (j + 1 < right) // 基準値の右に 2 以上要素があれば
  215. QSort(x, j + 1, right); // 右の配列を Q ソートする
  216. }
  217.  
  218. /* 配列の要素を交換する */
  219. void Swap(int x[ ], int i, int j)
  220. {
  221. int temp;
  222.  
  223. temp = x[i];
  224. x[i] = x[j];
  225. x[j] = temp;
  226. }
  227.  
  228. long Search(int x[], int n, long Target)
  229. {
  230. if(x[n] == Target){
  231. //printf("Answer: %d\n",x[n]);
  232. return 0;
  233. }
  234.  
  235. int i,j;
  236. int Answer,Answer2;
  237.  
  238. for(i=0;i<=n/2;i++){
  239. Answer = x[n-i];
  240. Answer2 = Target-Answer;
  241.  
  242. for(j=0;x[j]<=Answer2;j++){
  243. if(x[j] == Answer2){ //二組で見つかれば出力
  244. //printf("Answer: %d\nAnswer: %d\n",x[j],Answer);
  245. return 0;
  246. }
  247. }
  248. }
  249. return Target; //二組でも見つからんかったら知らん
  250. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement