Problem:
Put a number of n pieces of paper into your pocket, you can draw 4 of pieces of paper from your pocket, and put it back in your pocket every time you write down the number on the paper. If these 4 numbers are M, you win, or your friends win.
It's easy to write down the code below:
1 for(intA=0; a<n; a++){2 for(intb=0; b<n; b++){3 for(intC=0; c<n; C++){4 for(intD=0; d<n; d++){5 if(K[a] + k[b] + k[c] + k[d]==m) {6f =true;7 }8 }9 }Ten } One}
The above is the loop portion of the program that was originally documented. The innermost loop of D is doing the following:
Check if D makes ka+kb+kc+kd=m
By moving the equation, you get another way of expressing it:
Check if D makes KA=M-KB+KC+KD
is to check all the elements in the array k to determine if there are any m-kb+kc+kd.
Such a quick lookup, it is necessary to use the binary search algorithm.
1. Two-point search with O (N3LOGN)
Sort O (Nlogn) time
Cycle O (N3logn) time
1 intN,m,k[max];2 3 BOOLBinary_search (intx) {4 //x exists in the range of K[l],k[l+l]...k[r-l]5 intL=0, r=N;6 //repeated operation until the scope of existence is empty7 while(r-l>=l){8 intI= (L+R)/2;9 if(k[i]==x)return true;//Find xTen Else if(k[i]<x) l=i+1; One ElseR=i; A } - //no X found . - return false; the } - - viod Solve () { - //in order to find a binary search need to sort first +Sort (k,k+n); - + BOOLf=false; A for(intA=0; a<n; a++){ at for(intb=0; b<n; b++){ - for(intC=0;c<n; C++){ - //Replace the most internal loop with a binary lookup - if(Binary_search (m-k[a]-k[b]-K[c])) { -f=true; - } in } - } to } + if(f) Puts ("Yes"); - ElsePuts"No"); the}
Sort O (N2logn) time
Cycle O (N2logn) time
1 intN,m,k[max];2 intkk[max*MAX];3 4 BOOLBinary_search (intx) {5 //x exists in the range of Kk[l],kk[l+l]...kk[r-l]6 intL=0, r=n*N;7 //repeated operation until the scope of existence is empty8 while(r-l>=l) {9 intI= (L+R)/2;Ten if(kk[i]==x)return true;//Find x One Else if(kk[i]<x) l=i+1; A ElseR=i; - } - //no X found . the return false; - } - - viod Solve () { + //enumeration of K[c]+k[d] and - for(intC=0; c<n; C++){ + for(intD=0; d<n; d++){ Akk[c*n+d]=k[c]+K[d]; at } - } - //sort for two-point search -Sort (kk,kk+n*n); - - BOOLf=false; in for(intA=0; a<n; a++){ - for(intb=0; b<n; b++){ to //Replace the two loops in the inner part with a binary search + if(Binary_search (m-k[a]-K[b])) { -f=true; the } * } $ }Panax Notoginseng if(f) Puts ("Yes"); - ElsePuts"No"); the}
This problem requires both a binary search of this basic algorithmic knowledge, and a four-digit number to be divided into 22 of the imagination. Like this, from the high complexity of the algorithm, constantly reduce the complexity of the process of understanding the requirements of the problem, but also the design algorithm will often go through the process.
From:<< Challenge Program Design Competition >>
Thinking about the problem of drawing lots (dichotomy algorithm)