• ベストアンサー

最大値選択法

kazumeroの回答

  • kazumero
  • ベストアンサー率40% (20/49)
回答No.2

最初の交換のところはループの条件が書いてあります。 iの値が1からn-1までループが続くってことですね。 んで最大値のところは、 jの値がi+1からnまでループが続くってことです。 何故このようなループ条件なのか。 全部で数がn個ありますよね。 数を比較する時、1番目の数と2番目の数、1番目の数と3番目の数・・・という風にしますよね。 これを表しています。 ループに初めてたどり着いた時を考えてみます。 iには1が入ってますよね? とするとjはi+1ですので、2が入ってます。 iの値はkに代入されてるので、実際には、x(k)とx(j)、つまりx(1)とx(2)、つまりは1番目の数と2番目の数を比較しているわけです。 わかりにくかったらまた言ってください(^^;

sephiroth15873
質問者

お礼

ありがとうございます。そこの部分もよく分かりました。 あとはなんというか表現しづらいのですが…i=1~n-1までループすると思うんですが、その際x(j)>x(k)を満たすものはjがkになっていくんですよね? 例えば 4、9、8という列があるとすると i=1からこの作業をやっていくと、i=1の時x(1)をx(2)に代入、i=2の時x(2)はj→kの処理を受けないのでそのままになりますが、これは9がそのままになるのか、それとも9と交換した4がそのままになるのかどちらでしょう?あまり問題とは関係ないのですが気になってしまって…すみません^^;

関連するQ&A

  • 固有値の最大値

    下記の固有値の最大値に関する問題がわかりません。 Σ^(n)i=1 xi^2=1とする。このとき、実2次形式G(x)=Σ^(n)i,j=1 sij*xi*xj(ただし、sij=sji)の最大値はS=(sij)の固有値のうちの最大値と一致することを証明せよ。(i,jは全て下付き文字です) なにをどう進めて証明するのか見当もつきません。 式がみづらくて申し訳ありませんが、どなたか助けて下さい。

  • ラグランジュ乗数法による利潤最大化条件の導出

    「生産関数が次のようなコブ=ダグラス型であると仮定する。     x = l^a k^(1-a) (0≦a≦1) このとき、ラグランジュ乗数法を用いて、利潤最大化条件が     要素価格 = 限界生産力価値  であることを示せ。」という問題で、まず制約条件付き利潤最大化問題を     max px - w1l - w2l s.t. x = l^a k^(1-a) と置きました(w1, w2 はそれぞれ要素価格)。計算を進めると、最終的に     w1 = pa (k/l)^(1-a) w2 = p(1-a) (k/l)^a となったのですが、これをどうやって     w1 = pMPl, w2 = pMPk のかたちにもっていくのでしょうか。

  • ピボット選択がどのように行われてるか確かめたいので

    ピボット選択がどのように行われてるか確かめたいので 関数pivotを呼び出す前と呼び出して式を入れ替えた後のakk,ak+1k,...,ankを調べたいのですが どうすればいいのでしょうか? int gauss(double *x, double *a, double *b, int n) { int i,j,k; double tmp,p,sum; /* step 1: 前進消去 */ for(k=0; k<n-1;k++){ printf("---- Step %d ----\n",k+1); /* ピボットの選択 */ /*** 追加(2):ピボット選択前,選択して式を入れ替えた後それぞれの * a(k,k), a(k+1,k), ... , a(n-1,k) * を表示して,ピボット選択がどのように行なわれたか調べる. ***/ /*--- ピボット選択前の位置 ---*/ printf("-- before --\n"); /* a(k,k), a(k+1,k), ... , a(n-1,k) を表示させる.*/ /*----------------------------*/ j = pivot(a,n,k); /* j: ピボットとして選ばれたa(j,k)の行番号 */ if(j == ERROR) { return ERROR; } else { if(j != k) { /* ピボットにはa(k,k)ではなくa(j,k)が選ばれた.式の入れ替えが必要 */ /* Aのk行とj行の入れ替え.*/ for(i=0; i<n; i++){ tmp = a[n*k+i]; a[n*k+i] = a[n*j+i]; a[n*j+i] = tmp; } /* b[k] と b[j] の入れ替え */ tmp=b[j]; b[j]=b[k]; b[k]=tmp; } } /*--- ピボット選択をし,式の入れ替えをした直後の位置 ---*/ printf("-- after --\n"); /* a(k,k), a(k+1,k), ... , a(n-1,k) を表示させる. /*------------------------------------------------------*/ /* x[k] の消去 */ for(i=k+1; i<n; i++){ p=a[n*i+k]/a[n*k+k]; for(j=0; j<n; j++){ a[n*i+j]=a[n*i+j]-p*a[n*k+j]; printf("a[%d %d]=%lf",i,j,a[n*i+j]); } b[i]=b[i]-p*b[k]; printf("b[%d]=%lf\n",i,b[i]); } /*--- 追加(1):第k段によって x[k] を消去した後の,各式の状態を表示する. ---*/ /* a(1,1),a(1,2),...,a(1,n),b(1); a(2,1),a(2,2),... a(2,n),b(2), ... */ printf("k=%d\n",k); /*--------------------------------------------------------------------------*/ }/* step 2: 後退代入 */ for(k=n-1; k>=0; k--){ if(fabs(a[n*k+k]) < EPS) return(ERROR); sum=0.0; for(j=k+1; j<n; j++) sum+=a[n*k+j]*x[j]; x[k]=(b[k] - sum)/a[k*n+k]; } return 0; } int pivot(double *a, int n, int k) { int i,m; double d; /* ピボットの探索 */ m = k; d = fabs(a[k*n+k]); for(i=k+1; i<n; i++){ if(fabs(a[n*i+k]) > d){ m = i; d = fabs(a[n*i+k]); } } if(fabs(d) < EPS) { return ERROR; } else { return m; } }

  • 行列に関して。

    以下の行列を対角成分が最も大きくなるような プログラムをつくりたいのですが 0   1   4  3 7   0   1  -5 1    3   0   7 -2   4   4  -8 #include<stdio.h> #include<math.h> #include<stdlib.h> #define NUM 4 int main(){ /* 初期化 */ int i; /* ループ変数 (行)*/ int j; /* ループ変数 (列)*/ int k; /* ループ変数 */ int imax; /* 最大値のi成分 */ int jmax; /* 最大値のj成分 */ double nmax; /* 最大値を入れるための変数 */ double tmp; /* ソートのための一時的な変数 */ double eps = 1.0e-6; /* 判定値 */ double a[NUM][NUM] = { { 0.0, 1.0, 4.0, 3.0}, { 7.0, 0.0, 1.0, -5.0}, { 1.0, 3.0, 0.0, 7.0}, {-2.0, 4.0, 4.0, -8.0}}; /* 対象とする要素位置 = k */ for( k = 0 ; k < NUM ; k++ ){ /*対象とする要素位置 = k*/ nmax = 0.0;/* 初期化 */ imax = k;/* 初期化 0とは限らない */ jmax = k;/* 初期化 0とは限らない */ /* 1.絶対値の最大値を求める */ for( i = k ; i < NUM ; i++ ){ for( j = k ; j < NUM ; j++ ){ if(fabs(nmax) < fabs(a[i][j])){ nmax = a[i][j]; imax = i; jmax = j; /* 対象としている行列要素の中で,最大となる行列要素のi,j成分を探す */ /*ここに絶対値の最大値を求め、nmax、imax、jmaxに代入するプログラムを書く*/ /*絶対値の求め方、数学関数fabs(x)を用いる*/ } } } /* 2.行入れ換え */ if( k != imax ){/* 対象としている行と最大値を持つ行が同じなら,入れ替える必要が無い */ for( j = 0 ; j < NUM ; j++ ){ tmp=a[k][j]; a[k][j]=a[imax][j]; a[imax][j]=tmp;/* 対象としている行と最大値を持つ行との入れ替え */ /*ここに行の入れ替え行うプログラムを書く*/ } } /* 3.列入れ換え */ if( k != jmax ){/* 対象としている列と最大値を持つ列が同じなら,入れ替える必要が無い */ for( i = 0 ; i < NUM ; i++ ){ tmp=a[i][k]; a[i][k]=a[i][imax]; a[i][imax]=tmp;/*対象としている列と最大値を持つ列との入れ替え*/ /*ここに列の入れ替え行うプログラムを書く*/ } } } /* 結果の出力 */ for(i=0; i<NUM; i++){ for(j=0; j<NUM; j++){ printf("%5.1f ",a[i][j]); } printf("\n"); } /*ここに行列の表示プログラムを書く*/ return(0); } 上のぷろぐらむを実行しても、1個目のfor文の1ループ目で終了してしまい 1行目と、4行目を交換、4列目と1列目を交換した行列だけが表示されます。 結果が以下のような行列にするにはどう改善すればよいでしょうか? -8.0   -2.0  4.0  4.0 -5.0   7.0  1.0  0.0   3.0   0.0  4.0  1.0  7.0   1.0  0.0  3.0 です。

  • Jacobi法

    Jacobi法のアルゴリズム x[i]_{m+1} = ( b[i] - Σ{j≠i} a[i][j] * x[j]_{m} ) i=1,2,…,n m=0,1,2,… を基にプログラム(JAVA)を組んでみました。 (質問に直接関係ないところは省いています) for( m=0; m<100; m++ ) { for( i=0; i<n; i++ ) { for( j=0; j<i; j++) { if( i != j ) { tmp = tmp + a[i][j] * x2[j]; } } x1[i] = (b[i] - tmp) / a[i][i]; } } もう1つ。 for( k=0; k<100; k++ ) { for( i=0; i<n; i++ ) { xnew[i] = b[i]; for( j=0; j<n; j++ ) { if( j != i ) { xnew[i] = xnew[i] - a[i][j] * xold[j]; } } xnew[i] = xnew[i] / a[i][i]; } 2つ目のプログラムの方が正確です。 1つ目のプログラムだと間違いでしょうか? 私には2つ目のプログラムの xnew[i]=b[i]; の部分がどうしても理解できません。 これを行ってしまうと、アルゴリズムが x[i]_{m+1} = ( Σ{j≠i}b[i] - a[i][j] * x[j]_{m} ) になってしまわないでしょうか・・・? どちらでも良いのでしょうか? 納得いきません。 よろしくお願いします。

  • 配列 x に入っているデータの最大値、最小値を求めるサブルーチンとそのヒストグラムの作り方

    配列 x に入っているデータの最大値、最小値を求めるサブルーチン maxmin(x,n,xmax,xmin) を作り方を教えてください。 n はデータ数。 最大値、最小値はそれぞれ xmin, xmax に代入する。 次に、そのサブルーチンを用い、x に入っているデータのヒストグラムを作成するプログラムを作り方も教えてください。 (途中までしか分かりません) implicit real*8(a-h,o-z) real*8 x(10000) integer count(100) ndiv = 40 分割数は 40 にする n = 10000 データ数は 10000 dummy = rand(13) 乱数の初期化 do 10 i=1, n sum = 0.0d0 do 20 j=1,5 sum = sum + rand(0) 5個の乱数の和 20 continue x(i) = sum 10 continue call maxmin(x,n,xmax,xmin) 最大・最小値を求める dx = (xmax - xmin)/ndiv 分割幅 !!count をゼロで初期化する do ループを追加!!(よく分かりません) !!ヒストグラムを作成する do ループを追加!!(よく分かりません) do 100 k=1, ndiv write(6,*) xmin+(k-0.5d0)*dx, count(k) データの中心値と個数を出力 100 continue stop end subroutine maxmin(x,n,xmax,xmin) implicit real*8(a-h,o-z) real*8 x(*) !!この部分を作成してサブルーチンの完成のさせ方が分かりません!! return end ところどころが分かりません。 とても困っていますし、急いでいます。 だれか教えてください。 よろしくお願いします。

  • フローチャートの書き方

    要素数がnである配列aの要素の最大値を求めるアルゴリズムのループ端によるフローチャートを完成せよ(前判定繰返し) max =a[0] i=1; while i<n do{ if(a[i]>max)max=a[i]; i++; } フローチャートでかくとどうなりますか?

  • 連立方程式をSOR法を用いてコンピュータで解く

    { 2 1 1 }{ X1 } { 2 } { 2 3 1 }{ X2 }={ 4 } { 1 1 3 }{ X3 } {-1 } という問題をSOR法を用いてコンピュータ(fortran)で解け。ただし初期値は0とし許容誤差eps=10^-5とする。そこで私は次のようなプログラムで解きました。 ____dimension a(20,20),b(20),x(20),x0(20) ____open(5,file='senkei.d') ____open(6,file='senkei.r') ____open(7,file='senkei.k') ____read(5,*)n,max,eps,u ____read(5,*)((a(i,j),i=1,n),j=1,n) ____read(5,*)(b(i),i=1,n) ____read(5,*)(x0(i),i=1,n) ____do i=1,n ____ad=a(i,i) ____a(i,i)=0.0 ____b(i)=b(i)/ad ____do j=1,n ____a(i,j)=a(i,j)/ad ____end do ____end do ____do k=1,max ____do i=1,n ____w=0.0 ____do j=1,n ____if(j.lt.i)x0(j)=x(j) ____w=w+a(i,j)*x0(j) ____end do ____x(i)=u*(b(i)-w)+(1-u)*x(i) ____write(7,10)x(i) _10_format(3f10.5) ____end do ____w=0.0 ____do i=1,n ____w=w+(x(i)-x0(i))**2 ____end do ____w=sqrt(w/n) ____if(w.lt.eps)go to 20 ____do i=1,n ____x0(i)=x(i) ____end do ____end do ____write(6,*)'error' ____go to 30 _20_write(6,*)'sulution' ____write(6,40)(x(i),i=1,n) _40_format(3f15.5) _30_stop ____end max:最大繰り返し回数,u:緩和係数,a(i,j):係数行列, b(i):既知項,x(i):未知項としました。データではeps=0.00001,max=50,緩和係数uは0.8から0.1ずつ増やして1.5までそれぞれ答えを求めました。私のプログラムではu=1.1の時7回で収束しました。しかしu=1.5の時3回で収束したのですが答えはかなりの誤差ありました。許容誤差eps=10^-5としたのになぜ誤差が大きいまま、しかも三回で収束してしまったのかわかりません。誰かわかる方いらっしゃったら教えていただけませんか?長々と申し訳ありません。お願いします。

  • 交叉について

    c言語を使い始めて、TSPについて勉強中で、遺伝的アルゴリズムの交叉(順序交叉)について以下のプログラムを作ってみたのですが、凄く遅いです。答えはきちんと出るのですが、循環交叉を取り入れたプログラムは5000ループでも1秒弱で出るのに対して20秒近くかかってしまいます。ループに無駄が多そうなのですが思いつきません。ヒントでも宜しいのでご教授下さい。 順序交叉とは、例えば x[i] = 3,4,5,2,1とy[i] = 4,3,5,1,2(i = 0~)という数字が与えられたときtargetを2とすると x[i] = 3,4, y[i] = 4,3まではそのまま受け継ぎ、3以降は相手方の数字を左から順番に使われていないものを取り入れていくものです。この場合だと、x[i] = 3,4,5,1,2 y[i] = 4,3,5,2,1となります。 #define a 5 int main(void) {    int x[a] = {3, 4, 5, 2, 1}, y[a] = {4, 3, 5, 1, 2};    int target, i, j, k, l;    int x2[a], y2[a];    srand((unsigned)time(NULL));    target = rand () % a;    for (i = 0; i < target; i++) {       x2[i] = x[i];       y2[i] = y[i];    }    for (i = target; i < a; i++) {       x2[i] = 0;       y2[i] = 0;    }    j = 0;    k = 0;    while (k != a - target) {       for (i = 0; i < target + k; i++) {          for (l = 0; l < target + k; l++) {             if (x2[l] == y[j])                j++;          }       }       if (x2[target + k] != y[j]) {          x2[target + k] = y[j];          k++;          j++;       }       else          j++;    }    yについても同様の作業です }

  • このプログラミングって正しい?

    与えられた実行列X,Y,Z(配列名x、y、z)から、X-YZを計算して、行列W(配列名w)に格納するメソッドを完成する。 Public static void XminusXY( double[][] x,double[][] y,double[][] z, double[][] w){ double wij; int el=z[0].length, m=y.length, n=z.length; for(int i = 0; i<m; i++){ for(int j = 0; j<n-1; j++){ wij=xij for(int k=0; k<el; k++) wij += -y[i][k]*z[k][j]; w[i][j]=wij; } } }