算法设计例题
【动态规划专题】
例 1
正解:
(1)17条
(2)从A到B最短路径的长度是7,从A沿着右下方向取寻找路径,第一次找出距离A一步的点上的条数,第二次找出距离A两步的点上的条数,重复七次,假设 D[i][j] 是对应点上的条数,那么有 D[i][j] = D[i-1][j] + D[i][j-1] 。
(3)
例 2
正解:
input: A[1...n]
output: (p,q)
The pseudocode is as follows
operate()
{
mid = (1+n)/2
S[mid-1] = A[mid-1]
T[mid+1] = A[mid+1]
for(i = mid-2; i>=1 ;i--)
S[i] = S[i+1] + A[i]
for(i = mid+2; i<=n ;i++)
T[i] = T[i-1] + A[i]
max(S,p)
max(T,q)
return (p,q)
}
例 3
正解:
此问题的核心就是背包问题
(1)
if(j<ti)
X[i,j] = X[i-1,j]
else if(i>0&&j>ti)
X[i,j] = max{X[i-1,j],X[i-1,j-ti]+xi}
(2)
for i=0 to n
X[i,0] = 0
for j=0 to n
X[0,j] = 0 //initialization
for i=1 to C
for j=1 to n
X[i,j] = X[i-1,j]
if(j>=ti) X[i,j] = max{X[i,j],X[i-1,j-ti]+xi}
end for
end for
return X[n,C];
(3)
算法复杂度为表的大小O(nC)
例4
正解:
for i = 0 to n
V[i,0] = 0;
end for
for j = 0 to C
V[0,j] = 0;
end for
for i = 1 to n
for j = 1 to C
if(j < A[i]) then V[i,j] = V[i-1,j];
else V[i,j] = max{ V[i-1,j], V[i-1,j-A[i]]+B[i] };
end if
end for
end for
return V[n,C]
【随机算法专题】
(1)
Input : Point set P ,Reference point r
Output: Hypervolume hv
sort(P) // sort by the x-coordinate
hv = 0, y = r.y
for i=1 to |P|
hv += (y-P[i].y)*(r.x-P[i].x)
y = P[i].y
end for
Complexity: O(NlogN)
(2)
Input : Point set P ,Reference point r
Output: Hypervolume hv
x = min(P.x)
y = min(P.y)
sum = 0
for i=1 to N
r1 = rand()
r2 = rand()
rx = (r.x-x)*r1 + x
ry = (r.y-y)*r2 + y // coordinates of the random points
for j=1 to |P|
if P[j].x<=rx && P[j].y<=ry
sum++
break
end if // if it's within the range
end for
end for // generate N points
return (sum/N)*(r.x-x)*(r.y-y) // the correct hv
Complexity: O(N)
【分治专题】
例1
正解:
//
sum = 0;
i = A.rows;
j = 1;
while(i >= 1 && j <= A.col)
if(target == A[i][j])
sum++;
i--;
j++;
else if (target < A[i][j]) i--;
else j++;
end if
end while
例2
正解:
(1)
用分治的方法,设计递归子程序 Searchkth(A[] , low1 , high1 , B[] , low2 , high2 , k),用于求出A[low1…high1] 和 B[low2…high2] 中第k小元素,考虑 A[ |(low1+high1)/2| ] 和 B[ |(low2+high2)/2| ],
当 A[mid1] < B[mid2] 时 ,
情况一:mid1-low1+1+mid2-low2+1>=k, 则B[ |(low2+high2)/2| ] 之后的元素不可能是第k小元素;
情况二:mid1-low1+1+mid2-low2+1<k, 则A[ |(low1+high1)/2| ] 之前的元素不可能是第k小元素;
A[mid1]>=B[mid2]的情况可以类似推出,这是一种“简而治之”的算法设计思想
(2)
Input : A[1...n] , B[1...2n] , k (increasing order)
Output: the kth little element
Findkthelement()
{
x = Searchkth(A[],1,n,B[],1,2n,k)
output x
}
Searchkth(A[],low1,high1,B[],low2,high2,k)
{
if(low1>high1)
if(low2+k-1>high2) return ERROR
else return B[low2+k-1]
end if
if(low2>high2)
if(low1+k-1>high1) return ERROR
else return A[low1+k-1]
end if // 接口处
mid1 = |_(low1+high1)/2_|
mid2 = |_(low2+high2)/2_|
if(A[mid1]<B[mid2])
if(mid1-low1+1+mid2-low2+1>=k)
return Searchkth(A[],low1,high1,B[],low2,mid2,k)
else return Searchkth(A[],mid1+1,high1,B[],low2,high2,k-(mid1-low1+1))
end if
else
if(mid1-low1+1+mid2-low2+1>=k)
return Searchkth(A[],low1,mid1,B[],low2,high2,k)
else return Searchkth(A[],low1,high1,B[],mid2+1,high2,k-(mid2-low2+1))
end if
end if
}
complexity: O(logn)
(3)
一种向下挖掘深度的算法,复杂度是O(logn)
【回溯法专题】
正解:
call solve(1)
sum = 0
1. process solve(k)
for i=1 to N
c[k] = i;
if( (c[k] % k = 0) || (k % c[k] = 0) ) then
if( k = n) then sum++;
else solve(k+1);
end if
end if
end for
【贪心策略专题】
正解:
num = N
for i=1 to N
temp[i] = 0;
end for // 额外糖果
for i=1 to N-1
if(ratings[i+1] > ratings[i]) temp[i+1] = temp[i]+1;
end if
end for // 从左遍历
for i=N-1 to 1
if( (ratings[i] > ratings[i+1]) && (temp[i] <= temp[i+1]) ) then temp[i] = temp[i+1] +1;
end if
end for
num += sum(temp);
【其他课上题目】
不可能。
建模: 设棕色 x 只,灰色 y 只, 黑色 z 只。最后变成同一种颜色前提是存在两种数量相同的颜色。
(1)设棕色与黑色相遇 a 只, x = x - a , y = y +2a, z = z - a
(2)设灰色与黑色相遇 b 只, x = x + 2b, y = y + 2a - b, z = z - a - b
(3)若变为同一种颜色,则 x + 2b = y + 2a - b 即 y - x = 3*(b-a)
得出,若最终变为同一种颜色,需要任意两种颜色之差%3 = 0即可,故此题不可能变成同一种颜色。