マッチメイク

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
C初心者

マッチメイク

#1

投稿記事 by C初心者 » 16年前

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}
......
のようにただ組み合わせを列挙するだけでなく、日にちごとに組み合わせを並べるプログラムを考えています。
何か良い案があればお教えください。ちなみに上のプログラムは無視して結構です。この程度のことで初心者なもんですいません。

たいちう

Re:マッチメイク

#2

投稿記事 by たいちう » 16年前

n=4について、三日目以降の組み合わせを全て書き出してみましょう。できるだけ規則的に。
n=5についても同様。
n=6についてはやらなくても、そろそろ規則性を見つけることができるのでは?

C初心者

Re:マッチメイク

#3

投稿記事 by C初心者 » 15年前

n=4の場合は24通り
n=5の場合は120通りあるのでそこから規則を見つけ出すのは難しいかと

たいちう

Re:マッチメイク

#4

投稿記事 by たいちう » 15年前

その24通りと120通りをここに書いてみてください。

C初心者

Re:マッチメイク

#5

投稿記事 by C初心者 » 15年前

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}
特に規則性を見出すことはできませんでした。
数学的センスがないもんで。

non

Re:マッチメイク

#6

投稿記事 by non » 15年前

>特に規則性を見出すことはできませんでした。
規則性がないなら、答えを出せなかったと思いますが。

C++ならここが参考になります。
http://www.bohyoh.com/CandCPP/FAQ/FAQ00108.html

C初心者

Re:マッチメイク

#7

投稿記事 by C初心者 » 15年前

C++ではなくCです。
0-□,2-□,4-□,6-□
□の部分を順列で埋めてみるということですか?

non

Re:マッチメイク

#8

投稿記事 by non » 15年前

> C++ではなくCです。

そうですか、残念です。

> 0-□,2-□,4-□,6-□
> □の部分を順列で埋めてみるということですか?

No:40434 の24通りからすると、そうだと思いました。
最初の質問の意味がよくわかってないものですから。
リーグ戦の総当たりだけなら24通りもありませんし。

順列をCで求める方法はここが参考になります。
私なら、再帰呼び出しを使う方法で解きます。
http://jubilo.cis.ibaraki.ac.jp/~isemba ... OG/c.shtml

zard

Re:マッチメイク

#9

投稿記事 by zard » 15年前

問題はどうやって奇数番号の順列にするかですね
初心者にはキツイです

たいちう

Re:マッチメイク

#10

投稿記事 by たいちう » 15年前

1~nの順列を生成して、2倍して1を引けば良い。

C初心者

Re:マッチメイク

#11

投稿記事 by C初心者 » 15年前

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!通り最初から生成するほうが普通ですよね?

たいちう

Re:マッチメイク

#12

投稿記事 by たいちう » 15年前

タグの使い方を間違っているのでソースコードを読みにくい。
・rをnに置き換えて、不要な部分を削ればよい。
・main()の最後にreturn 0;を追加する。
・私も順列生成は再帰を使う。その方がプログラムが理解しやすいから。
・普通かどうかは状況次第。

Eeel

コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です

#13

投稿記事 by Eeel » 15年前

[color=#e0e0ff" face="monospace]
class CTest
{
public:
&#160;&#160;&#160;&#160;int *m_t;

&#160;&#160;&#160;&#160;//コンストラクタ
&#160;&#160;&#160;&#160;CTest(){
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;printf("コンストラクタ\n");
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_t = new int;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;*m_t = 10;
&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;//コピーコンストラクタ
&#160;&#160;&#160;&#160;CTest(const CTest& obj){
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;printf("コピーコンストラクタその1\n");
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;CTest();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//コンストラクタを呼び出す
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;printf("コピーコンストラクタその2\n");
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;*m_t = *obj.m_t;
&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;//デストラクタ
&#160;&#160;&#160;&#160;~CTest(){
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;printf("デストラクタ\n");
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delete[/url] m_t;
&#160;&#160;&#160;&#160;}
};

int main()
{
&#160;&#160;&#160;&#160;CTest a;

&#160;&#160;&#160;&#160;*a.m_t = 20;

&#160;&#160;&#160;&#160;CTest b = a; //ここでコピーコンストラクタが呼ばれる

&#160;&#160;&#160;&#160;return 0;
}
[/color]

実行結果:
コンストラクタ          ←aのコンストラクタ
コピーコンストラクタその1  ←bのコピーコンストラクタその1
コンストラクタ          ←bのコンストラクタ
デストラクタ           ←bのデストラクタ
コピーコンストラクタその2  ←bのコピーコンストラクタその2

この後は、デストラクタでメモリが開放されてしまっているのでエラーが発生します。
デストラクタはコンストラクタの直後に呼ばれているようです。
コンストラクタを呼ばなければデストラクタも呼ばれないので、
コンストラクタの内容をコピーコンストラクタに書く事で一応の問題回避はできました。
しかし、何故このような動作になるのでしょうか?

Justy

Re:コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です

#14

投稿記事 by Justy » 15年前


>デストラクタはコンストラクタの直後に呼ばれているようです
>何故このような動作になるのでしょうか?

 そういうものだから、では身も蓋もないのですが
CTest();と書いた場合、コンストラクタだけを
呼び出すものではありません。

 単純に CTestクラスの一時オブジェクトを作って
捨てているだけになります。
 
 なので、コピーコンストラクタ内の this->m_tは未初期化のまま、ということなります。


 あと、deleteではなくdeleteで。

Eeel

Re:コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です

#15

投稿記事 by Eeel » 15年前

コンストラクタの他にinitialize()などを作って初期化処理を分ける理由がよくわかりました。
再初期化しようと思ってコンストラクタを明示的に読んでもだめなんですね。

delete[/url]は配列でなくても開放できる、と覚えていたので
常にdelete[/url]でいいやと思っていました。
しっかり確認したところ処理系に依存するようでした。

どちらもとても勉強になりました。
ありがとうございました。

バグ

Re:コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です

#16

投稿記事 by バグ » 15年前

コピーコンストラクタを使いたいのならば…


CTest b(a);


これでいけるはず…

Eeel

Re:コピーコンストラクタ内でのコンストラクタ呼び出し時の動作について質問です

#17

投稿記事 by Eeel » 15年前

コピーコンストラクタを使いたいというより、
コピーコンストラクタ内でコンストラクタを呼び出したかったんです。
場所に関係なく明示的なコンストラクタの呼び出しは一時オブジェクトを作って
それのコンストラクタを実行するというのが正解だったようです。

閉鎖

“C言語何でも質問掲示板” へ戻る