私はこの問題をの除算&の征服者を使用して解決しました。
論理
まず最初に配列の集合を考えてみましょう。この配列から最小の配列グループを探したいと思います。その組み合わせは1だけの配列です。
&グループ内のすべての配列を、残りの配列から最も小さいグループを見つけて、グループ&の配列の組み合わせが条件を満たすようにするだけです。 &最小の組み合わせ(配列のグループ+現在の配列)は私たちの解決策です。
問題の再帰的な定義を単純に与えることができます。ここ
ソリューション
#include<stdio.h>
#define L 4 //length of the array
#define N 4 //number of arrays
int best[N]; //array to keep track of best combination.
int nbest=N; //number of best arrays in best combination.
int D[N][L]={{1,0,1,0},{1,0,0,1},{0,1,1,0},{0,1,0,1}}; //data
int func(int track[],int ar[],int d); //get best combination
int * copy(int *a,int len); //copy contant of a to b.
int * combine(int a[],int b[],int len);
int main()
{
int i,j;
int empty[L]={0,0,0,0};//initial combination
int init[N]={-1,-1,-1,-1};//initial track.
// initialize 'best' array.
for(i=0;i<N;i++)
best[i]=-1;
// initial function call
func(init,empty,0);
// print the result.
printf("best combination..\n");
for(i=0;i<nbest;i++){
for(j=0;j<L;j++)
printf("%d, ",D[best[i]][j]);
printf("\n");
}
return 0;
}
/*
* this is recursive function work on data array 'D'.
* array 'track' is used to keep track of the arrays of current combination.
* array 'ar' is indicate the current combination.
* int 'd' indicate the number of arrays in current combination.
*/
int func(int track[],int ar[],int d){
int i,j,*t,*tr;
if(d>=N) //check if there are arrays remain to combine.
return 0;
if(check(ar,L)){ //check if the combination is valid.
if(nbest>d){ //check if the current solution is better then the best.
nbest=d;
for(i=0;i<d;i++)
best[i]=track[i];
}
return 1;
}
tr=copy(track,N); //make local copy of track.
for(i=0;i<N;i++){ // make combination with all remaining arrays.
if(isin(tr,i)) // check if current array is already in combination.
continue;
t=copy(ar,L); //make local copy of current combination.
tr[d]=i; // update track array to track current array.
t=combine(t,D[i],L); // combine the array with current combination.
if(func(tr,t,d+1)){ // recursive call, brake the loop if the current combination is valid.
break;
}
}
return 0;
}
int * combine(int a[],int b[],int len){ // return combination of array 'a' & 'b'.
int *c=(int *)calloc(len,sizeof(int));
int i;
for(i=0;i<len;i++){
c[i]=a[i]||b[i];
}
return c;
}
int * copy(int *a,int len){ // this function return copy of array 'a' of length 'len'
int i;
int *t=(int *)calloc(len,sizeof(int));
for(i=0;i<len;i++)
t[i]=a[i];
return t;
}
int check(int a[],int len){ // check if the array is valid combination. i.e. all elememnts are 1.
int i;
for(i=0;i<len;i++)
if(a[i]!=1)
return 0;
return 1;
}
int isin(int *ar,int index){ // return 1 if int 'index' is exist in array 'ar'.
int i;
for(i=0;i<N;i++)
if(ar[i]==index)
return 1;
return 0;
}
私たちは、インスタンスで発見した最高のソリューションを追跡するために、配列best
を使用していました。
1)残りの部分を、必要な位置にある1の合計数でランク付けします。 2)最高ランクを取る。 3)反復 – john
申し訳ありませんが、分かりません。残りは何ですか?埋められていないゼロ? –
ジョンは貪欲なアルゴリズムを提案しましたが、必ずしも最良の結果を出すわけではありません。例:{1、0、1、0、1、0}、{1,1,0,0,0,0}、{0,0,1,1,0,0}、{0,0、 0,0,1,1}]となる。最良の解決策は、最初の配列を除くすべての配列を取ることですが、貪欲アルゴリズムは最初の配列から始まります。なぜなら、3つの配列を持っていて、他の配列も追加しなければならないからです。 – maraca