マッチメイク
マッチメイク
C言語を始めて半年の者です。
nチームからなるリーグ戦で考えられる対戦組み合わせを全部求めるプログラムを考えてみました↓
nチームそれぞれに1~nの番号をふり、その番号をチーム名とする。
#include <stdio.h>
int main(void)
{
int i, j, n;
FILE *fp;
printf("Please input n:\n");
scanf("%d", &n);
fp = fopen ("data", "w");
for(i = 1; i <= n; i++){
for(j = i; j <= n; j++){
if(i != j){
fprintf(fp, "%d %d\n", i, j);
}
}
}
fclose(fp);
return 0;
}
今度はA={1,3,5,..,2n-1}←(奇数番号)とB={0,2,4,...,2n-2}←(偶数番号)のnチームずつ2リーグに分け
交流戦の対戦組み合わせをすべて求めるプログラムを作成しようとしていますが、
なかなか良い案が浮かびません。さらに欲を言えば例えば
例)n=4の場合 A={1,3,5,7} B={0,2,4,6}
一日目{1-0,3-2,5-4,7-6}
二日目{1-2,3-4,5-6,7-0}
......
のようにただ組み合わせを列挙するだけでなく、日にちごとに組み合わせを並べるプログラムを考えています。
何か良い案があればお教えください。ちなみに上のプログラムは無視して結構です。この程度のことで初心者なもんですいません。
nチームからなるリーグ戦で考えられる対戦組み合わせを全部求めるプログラムを考えてみました↓
nチームそれぞれに1~nの番号をふり、その番号をチーム名とする。
#include <stdio.h>
int main(void)
{
int i, j, n;
FILE *fp;
printf("Please input n:\n");
scanf("%d", &n);
fp = fopen ("data", "w");
for(i = 1; i <= n; i++){
for(j = i; j <= n; j++){
if(i != j){
fprintf(fp, "%d %d\n", i, j);
}
}
}
fclose(fp);
return 0;
}
今度はA={1,3,5,..,2n-1}←(奇数番号)とB={0,2,4,...,2n-2}←(偶数番号)のnチームずつ2リーグに分け
交流戦の対戦組み合わせをすべて求めるプログラムを作成しようとしていますが、
なかなか良い案が浮かびません。さらに欲を言えば例えば
例)n=4の場合 A={1,3,5,7} B={0,2,4,6}
一日目{1-0,3-2,5-4,7-6}
二日目{1-2,3-4,5-6,7-0}
......
のようにただ組み合わせを列挙するだけでなく、日にちごとに組み合わせを並べるプログラムを考えています。
何か良い案があればお教えください。ちなみに上のプログラムは無視して結構です。この程度のことで初心者なもんですいません。
Re:マッチメイク
24通り
{0-1,2-3,4-5,6-7}
{0-1,2-3,4-7,6-5}
{0-3,2-1,4-5,6-7}
{0-1,2-5,4-3,6-7}
{0-1,2-7,4-5,6-3}
{0-5,2-3,4-1,6-7}
{0-7,2-3,4-5,6-1}
{0-1,2-5,4-7,6-3}
{0-3,2-5,4-1,6-7}
{0-1,2-7,4-3,6-5}
{0-5,2-1,4-3,6-7}
{0-5,2-3,4-7,6-1}
{0-7,2-3,4-1,6-5}
{0-7,2-1,4-5,6-3}
{0-3,2-7,4-5,6-1}
{0-7,2-1,4-3,6-5}
{0-3,2-5,4-7,6-1}
{0-3,2-1,4-7,6-5}
{0-7,2-5,4-3,6-1}
{0-5,2-1,4-7,6-3}
{0-3,2-7,4-1,6-5}
{0-7,2-5,4-1,6-3}
{0-5,2-7,4-3,6-1}
{0-5,2-7,4-1,6-3}
特に規則性を見出すことはできませんでした。
数学的センスがないもんで。
{0-1,2-3,4-5,6-7}
{0-1,2-3,4-7,6-5}
{0-3,2-1,4-5,6-7}
{0-1,2-5,4-3,6-7}
{0-1,2-7,4-5,6-3}
{0-5,2-3,4-1,6-7}
{0-7,2-3,4-5,6-1}
{0-1,2-5,4-7,6-3}
{0-3,2-5,4-1,6-7}
{0-1,2-7,4-3,6-5}
{0-5,2-1,4-3,6-7}
{0-5,2-3,4-7,6-1}
{0-7,2-3,4-1,6-5}
{0-7,2-1,4-5,6-3}
{0-3,2-7,4-5,6-1}
{0-7,2-1,4-3,6-5}
{0-3,2-5,4-7,6-1}
{0-3,2-1,4-7,6-5}
{0-7,2-5,4-3,6-1}
{0-5,2-1,4-7,6-3}
{0-3,2-7,4-1,6-5}
{0-7,2-5,4-1,6-3}
{0-5,2-7,4-3,6-1}
{0-5,2-7,4-1,6-3}
特に規則性を見出すことはできませんでした。
数学的センスがないもんで。
Re:マッチメイク
>特に規則性を見出すことはできませんでした。
規則性がないなら、答えを出せなかったと思いますが。
C++ならここが参考になります。
http://www.bohyoh.com/CandCPP/FAQ/FAQ00108.html
規則性がないなら、答えを出せなかったと思いますが。
C++ならここが参考になります。
http://www.bohyoh.com/CandCPP/FAQ/FAQ00108.html
Re:マッチメイク
> C++ではなくCです。
そうですか、残念です。
> 0-□,2-□,4-□,6-□
> □の部分を順列で埋めてみるということですか?
No:40434 の24通りからすると、そうだと思いました。
最初の質問の意味がよくわかってないものですから。
リーグ戦の総当たりだけなら24通りもありませんし。
順列をCで求める方法はここが参考になります。
私なら、再帰呼び出しを使う方法で解きます。
http://jubilo.cis.ibaraki.ac.jp/~isemba ... OG/c.shtml
そうですか、残念です。
> 0-□,2-□,4-□,6-□
> □の部分を順列で埋めてみるということですか?
No:40434 の24通りからすると、そうだと思いました。
最初の質問の意味がよくわかってないものですから。
リーグ戦の総当たりだけなら24通りもありませんし。
順列をCで求める方法はここが参考になります。
私なら、再帰呼び出しを使う方法で解きます。
http://jubilo.cis.ibaraki.ac.jp/~isemba ... OG/c.shtml
Re:マッチメイク
pre
#include <stdio.h>
int main(){
int a[99999];
int d[99999];
int i,j;
int n; /* 要素の個数 */
int r; /* 取り出す要素数 */
int count; /* 順列の個数 */
while(1){
printf("要素の個数:");
scanf("%d",&n);
printf("取り出す要素数:");
scanf("%d",&r);
printf("\n");
if(n<=0){
break;
}
count=0;
for(i=1;i<=r;i++){
a=1;
}
do
{
d[0] = 1;
for(j=1;j<=n;j++){
d[j]=0;
}
a[0]=0;
i = r;
d[a]++;
while(d[a]==1){
i--;
d[a]++;
}
if(i==0){
count++;
printf("%6.0d:",count);
for(i=1;i<=r;i++){
printf("%2d ",2*a-1);
}
printf("\n");
}
i = r;
a++;
while(a>n){
a=1;
i--;
a++;
}
} while(i>=1);
printf("\n");
printf("%d通り\n",count);
printf("\n");
}
}
/pre
↑はどうでしょうか?何か不備がありましたら、アドバイスください。
これでn=4,r=4とすると24通り生成できましたが、そもそも順列にしなくても
n!通り最初から生成するほうが普通ですよね?
#include <stdio.h>
int main(){
int a[99999];
int d[99999];
int i,j;
int n; /* 要素の個数 */
int r; /* 取り出す要素数 */
int count; /* 順列の個数 */
while(1){
printf("要素の個数:");
scanf("%d",&n);
printf("取り出す要素数:");
scanf("%d",&r);
printf("\n");
if(n<=0){
break;
}
count=0;
for(i=1;i<=r;i++){
a=1;
}
do
{
d[0] = 1;
for(j=1;j<=n;j++){
d[j]=0;
}
a[0]=0;
i = r;
d[a]++;
while(d[a]==1){
i--;
d[a]++;
}
if(i==0){
count++;
printf("%6.0d:",count);
for(i=1;i<=r;i++){
printf("%2d ",2*a-1);
}
printf("\n");
}
i = r;
a++;
while(a>n){
a=1;
i--;
a++;
}
} while(i>=1);
printf("\n");
printf("%d通り\n",count);
printf("\n");
}
}
/pre
↑はどうでしょうか?何か不備がありましたら、アドバイスください。
これでn=4,r=4とすると24通り生成できましたが、そもそも順列にしなくても
n!通り最初から生成するほうが普通ですよね?
コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です
[color=#e0e0ff" face="monospace]
class CTest
{
public:
    int *m_t;
    //コンストラクタ
    CTest(){
        printf("コンストラクタ\n");
        m_t = new int;
        *m_t = 10;
    }
    //コピーコンストラクタ
    CTest(const CTest& obj){
        printf("コピーコンストラクタその1\n");
        CTest();                                    //コンストラクタを呼び出す
        printf("コピーコンストラクタその2\n");
        *m_t = *obj.m_t;
    }
    //デストラクタ
    ~CTest(){
        printf("デストラクタ\n");
        delete[/url] m_t;
    }
};
int main()
{
    CTest a;
    *a.m_t = 20;
    CTest b = a; //ここでコピーコンストラクタが呼ばれる
    return 0;
}
[/color]
実行結果:
コンストラクタ ←aのコンストラクタ
コピーコンストラクタその1 ←bのコピーコンストラクタその1
コンストラクタ ←bのコンストラクタ
デストラクタ ←bのデストラクタ
コピーコンストラクタその2 ←bのコピーコンストラクタその2
この後は、デストラクタでメモリが開放されてしまっているのでエラーが発生します。
デストラクタはコンストラクタの直後に呼ばれているようです。
コンストラクタを呼ばなければデストラクタも呼ばれないので、
コンストラクタの内容をコピーコンストラクタに書く事で一応の問題回避はできました。
しかし、何故このような動作になるのでしょうか?
class CTest
{
public:
    int *m_t;
    //コンストラクタ
    CTest(){
        printf("コンストラクタ\n");
        m_t = new int;
        *m_t = 10;
    }
    //コピーコンストラクタ
    CTest(const CTest& obj){
        printf("コピーコンストラクタその1\n");
        CTest();                                    //コンストラクタを呼び出す
        printf("コピーコンストラクタその2\n");
        *m_t = *obj.m_t;
    }
    //デストラクタ
    ~CTest(){
        printf("デストラクタ\n");
        delete[/url] m_t;
    }
};
int main()
{
    CTest a;
    *a.m_t = 20;
    CTest b = a; //ここでコピーコンストラクタが呼ばれる
    return 0;
}
[/color]
実行結果:
コンストラクタ ←aのコンストラクタ
コピーコンストラクタその1 ←bのコピーコンストラクタその1
コンストラクタ ←bのコンストラクタ
デストラクタ ←bのデストラクタ
コピーコンストラクタその2 ←bのコピーコンストラクタその2
この後は、デストラクタでメモリが開放されてしまっているのでエラーが発生します。
デストラクタはコンストラクタの直後に呼ばれているようです。
コンストラクタを呼ばなければデストラクタも呼ばれないので、
コンストラクタの内容をコピーコンストラクタに書く事で一応の問題回避はできました。
しかし、何故このような動作になるのでしょうか?
Re:コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です
>デストラクタはコンストラクタの直後に呼ばれているようです
>何故このような動作になるのでしょうか?
そういうものだから、では身も蓋もないのですが
CTest();と書いた場合、コンストラクタだけを
呼び出すものではありません。
単純に CTestクラスの一時オブジェクトを作って
捨てているだけになります。
なので、コピーコンストラクタ内の this->m_tは未初期化のまま、ということなります。
あと、deleteではなくdeleteで。
Re:コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です
コンストラクタの他にinitialize()などを作って初期化処理を分ける理由がよくわかりました。
再初期化しようと思ってコンストラクタを明示的に読んでもだめなんですね。
delete[/url]は配列でなくても開放できる、と覚えていたので
常にdelete[/url]でいいやと思っていました。
しっかり確認したところ処理系に依存するようでした。
どちらもとても勉強になりました。
ありがとうございました。
再初期化しようと思ってコンストラクタを明示的に読んでもだめなんですね。
delete[/url]は配列でなくても開放できる、と覚えていたので
常にdelete[/url]でいいやと思っていました。
しっかり確認したところ処理系に依存するようでした。
どちらもとても勉強になりました。
ありがとうございました。
Re:コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です
コピーコンストラクタを使いたいというより、
コピーコンストラクタ内でコンストラクタを呼び出したかったんです。
場所に関係なく明示的なコンストラクタの呼び出しは一時オブジェクトを作って
それのコンストラクタを実行するというのが正解だったようです。
コピーコンストラクタ内でコンストラクタを呼び出したかったんです。
場所に関係なく明示的なコンストラクタの呼び出しは一時オブジェクトを作って
それのコンストラクタを実行するというのが正解だったようです。