#include <stdio.h> #include <stdlib.h> int num = 0; //2つの数の和がXになるものを探す関数 void combi_sum_two(int A[], int p, int w, int n, int r, int X, int array[]); //いくつかの数の和がXになるものを探す関数 void combi_sum(int A[], int p, int w, int n, int r, int X, int array[]); //2つの数の差がXになるものを探す関数 void combi_difference(int A[], int p, int w, int n, int r, int X, int array[]); //2つの数を足し引きしてXになるものを探す関数 void combi_sum_difference_two(int A[], int p, int w, int n, int r, int X, int array[]); //いくつかの数を足し引きしてXになるものを探す関数 void combi_sum_difference(int A[], int p, int w, int n, int r, int X, int array[]); int main(void) { //基本問題1 int i; int N = 0; int r = 2; int X = 0; int K[190]; int array[20]; printf("<基本問題1>\n入力する整数の個数N(2<N<21)を入力してください。\nN="); scanf_s("%d", &N); if (N < 3 || N > 20) { printf("N=%dは2<N<21を満たしていません。プログラムを終了します。\n", N); exit(0); } printf("%d個の整数を入力してください。\n", N); for (i = 0; i < N; i++) { scanf_s("%d", &array[i]); } printf("2つの数値の和Xがいくつになる組み合わせを探しますか。\nX="); scanf_s("%d", &X); combi_sum_two(K, r, N - r, N, r, X, array); //基本問題2 //初期化 num = 0; N = 0; r = 0; X = 0; printf("<基本問題2>\n入力する整数の個数N(2<N<21)を入力してください。\nN="); scanf_s("%d", &N); if (N < 3 || N > 20) { printf("N=%dは2<N<21を満たしていません。プログラムを終了します。\n", N); exit(0); } printf("%d個の整数を入力してください。\n", N); for (i = 0; i < N; i++) { scanf_s("%d", &array[i]); } printf("いくつかの数値の和Xがいくつになる組み合わせを探しますか。\nX="); scanf_s("%d", &X); combi_sum(K, r, N - r, N, r, X, array); //基本問題3 //初期化 num = 0; N = 0; r = 2; X = 0; printf("<基本問題3>\n入力する整数の個数N(2<N<21)を入力してください。\nN="); scanf_s("%d", &N); if (N < 3 || N > 20) { printf("N=%dは2<N<21を満たしていません。プログラムを終了します。\n", N); exit(0); } printf("%d個の整数を入力してください。\n", N); for (i = 0; i < N; i++) { scanf_s("%d", &array[i]); } printf("2つの数値の差Xがいくつになる組み合わせを探しますか。\nX="); scanf_s("%d", &X); combi_difference(K, r, N - r, N, r, X, array); //基本課題4 //初期化 num = 0; N = 0; r = 0; X = 0; printf("<基本問題4>\n入力する整数の個数N(2<N<21)を入力してください。\nN="); scanf_s("%d", &N); if (N < 3 || N > 20) { printf("N=%dは2<N<21を満たしていません。プログラムを終了します。\n", N); exit(0); } printf("%d個の整数を入力してください。\n", N); for (i = 0; i < N; i++) { scanf_s("%d", &array[i]); } printf("いくつかの数値を足し引きした結果Xがいくつになるものを探しますか。\nX="); scanf_s("%d", &X); combi_sum_difference(K, r, N - r, N, r, X, array); return 0; } //2つの数の和がXになるものを探す関数 void combi_sum_two(int A[], int p, int w, int N, int r, int X, int array[]) { //ループ脱出条件 if (p > 0) { int i; for (i = 0; i <= w; i++){ A[p] = i; combi_sum_two(A, p - 1, w - i, N, r, X, array); //再起 } } else { int i, j, m; int sum = 0; int array_index[20]; //0と1を記録する配列 num++; printf("%d:\t", num); m = 0; for (i = 1; i <= r; i++) { for (j = 0; j < A[i]; j++, m++) { array_index[m] = 0; } array_index[m] = 1; //1を出力した場合、和をとる sum += array[m]; m++; } for (; m < N; m++) { array_index[m] = 0; } //0と1を出力 for (j = 0; j < m; j++) { printf("%d", array_index[j]); } //和を出力 printf("\tsum = %d", sum); //和とXが同値なら1を出力した位置にある数値を出力 if (sum == X) { printf("\t和が%dになる組み合わせは", X); for (j = 0; j < N; j++) { if (array_index[j] == 1) { printf(",%d", array[j]); } } printf("です。"); } printf("\n"); } } //いくつかの数の和がXになるものを探す関数 void combi_sum(int A[], int p, int w, int N, int r, int X, int array[]) { for (r = 1; r <= N; r++) { combi_sum_two(A, r, N - r, N, r, X, array); //2つの数の和がXになるものを探す関数 } } //2つの数の差がXになるものを探す関数 void combi_difference(int A[], int p, int w, int N, int r, int X, int array[]) { if (p > 0) { int i; for (i = 0; i <= w; i++){ A[p] = i; combi_difference(A, p - 1, w - i, N, r, X, array); } } else { int i, j, m; int count = 0; int difference_two[2]; int array_index[20]; num++; printf("%d:\t", num); m = 0; for (i = 1; i <= r; i++) { for (j = 0; j < A[i]; j++, m++) { array_index[m] = 0; } array_index[m] = 1; difference_two[count] = array[m]; count++; m++; } for (; m < N; m++) { array_index[m] = 0; } for (j = 0; j < m; j++) { printf("%d", array_index[j]); } printf("\tABS(difference) = %d", abs(difference_two[0] - difference_two[1])); if (abs(difference_two[0] - difference_two[1]) == abs(X)) { printf("\t2つの数の差が%dになる組み合わせは", X); for (j = 0; j < N; j++) { if (array_index[j] == 1) { printf(",%d", array[j]); } } printf("です。"); } printf("\n"); } } //2つの数を足し引きしてXになるものを探す関数 void combi_sum_difference_two(int A[], int p, int w, int N, int r, int X, int array[]) { if (p > 0) { int i; for (i = 0; i <= w; i++){ A[p] = i; combi_sum_difference_two(A, p - 1, w - i, N, r, X, array); } } else { int i, j, m; int sum = 0; int count = 0; int array_index[20]; //0と1を記録する配列 int array_suuti[20]; //1を出力した位置の数値を受け取る配列 num++; printf("%d:\t", num); m = 0; //array_suutiの初期化 for (i = 0; i < N; i++) { array_suuti[i] = 0; } for (i = 1; i <= r; i++) { for (j = 0; j < A[i]; j++, m++) { array_index[m] = 0; } array_index[m] = 1; //1を出力した位置の数値をarray_suutiに格納 array_suuti[count] = array[m]; count++; m++; } for (; m < N; m++) { array_index[m] = 0; } //0と1を出力 for (i = 0; i < m; i++) { printf("%d", array_index[i]); } printf("\t"); //1を出力した位置の数値の足し引きをbit全探索 int bit; int S[20]; for (bit = 0; bit < (1 << count); bit++) { // Sの初期化 for (j = 0; j < count; j++) { S[j] = 0; } sum = 0; for (j = 0; j < count; j++) { if (bit & (1 << j)) { S[j] = 1; sum += array_suuti[j]; //1の場合、数値を足す } else{ sum += (-1) * (array_suuti[j]); //1でない場合、数値を引く } } if (sum == X) { printf("\t足し引きして%dになる数値の組み合わせは", X); for (j = 0; j < count; j++) { printf(",%d ", array_suuti[j]); } printf("です。"); break; } } printf("\n"); } } //いくつかの数を足し引きしてXになるものを探す関数 void combi_sum_difference(int A[], int p, int w, int N, int r, int X, int array[]) { for (r = 1; r <= N; r++) { combi_sum_difference_two(A, r, N - r, N, r, X, array); //2つの数を足し引きしてXになるものを探す関数 } }