Recursive Property를 세운다. (fn = fn-1 + fn-2)
작은 문제부터 해결해가며 bottom-up 방식으로 문제를 해결한다.
//Recursive
int bin(int n, int. k){
if(n==k)
return 1;
else
return bin(n-1,k)+bin(n-1,k-1);
}
→DP 사용해서 해결 가능하다.
//DP
int bin2(int n, int k){
index i,k;
int B[0..n][0..k];
for (i=0;i<=n;i++){
for(j=0;j<=min(i,k);j++){
if(j==0 | i==j)
return 1;
else
B[i][j] = B[i-1][k] + B[i-1][k-1];
}
}
return B[n][k];
}
G= (V,E) weighted directed graph(acyclic - 사이클 없다.)에서 그래프상의 각 정점에서 정점까지의 최단거리를 구한다.
모든 최단거리 문제는 정점 i에서 j까지 거리를 저장하는 를 구하는 것이 목표.
: vi에서 vj까지 {v1,v2..vk}를 거쳐서가는 최단거리.
이고 구하고자 하는 건
Recursive Property
void floyd (int n, const number W[][], number D[][]){
index i,j,k;
D = W;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
D[i][j] = min(D[i][j],D[i][k]+D[k][j]);
}
→
void folyd2(int n, const number W[][], number D[][], index P[][]){
index i,j,k;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
P[i][j]=0;
D=W;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(D[i][k]+D[k][j]<D[i][j]){
D[i][j]= D[i][k] + D[k][j];
P[i][j]= k;
}
}
// 정점에서 다른 정정으로 가는 최단거리 사이에 있는 정점 출력
void path (index q, r){
if(P[q][r]!=0){
path(q,P[q][r]);
cout<<"v"<<P[q][r];
path(P[q][r],r);
}
}
Principle of Optimality
: Instance에 대한 Optimal Solution은 그것을 이루는 Subinstances의 solution도 Optimal하다.
→ DP 사용하기 위한 조건
struct nodetype{
keytype key;
nodetype* left;
nodetype* right;
};
typedef nodetype* node_pointer;
void search(node_pointer tree, keytype keyin, node_pointer &p){
bool found;
p=tree;
found=false;
while(!found){
if(p->key == keyin)
found = true;
else if (keyin < p->key)
p = p->left; // 왼쪽 child로 이동
else
p = p->right; // 오른쪽 child로 이동
}
}
주어진 key 찾는 시간 : depth(key) +1
인 n개의 키가 순서대로 존재
: 가 찾는 값일 확률
: 를 찾기 위한 비교 횟수
⇒ 를 최소화 한다.
부터 까지 정렬된 tree는 을 최소화하는데 이를 Optimal 이라한다.
:
Principle of Optimality
∴
()
일반화
void optsearchtree(int n ,const float p[], float& minavg, index R[][]){
index i,j,k,diagonal;
float A[1..n+1][0..n];
for(i=1; i<=n; i++){
A[i][i-1]=0;
A[i][i]= P[i];
R[i][i]=i;
R[i][i-1]=0;
}
A[n+1][n]=0;
R[n+1][n]=0;
for(diagoanl=1; diagonal<=n-1; diagonal++)
for(i=1; i<=n-diagonal;i++){
j=i+diagonal;
A[i][j] = min(A[i][k-1]+A[k+1][j]) + sum(p_m);
R[i][j] = k // minimum 만드는 k
}
minavg= A[1][n];
)
//Build OBST
node_pointer tree(index i,j){
index x;
node_pointer p;
k= R[i][j];
if(k==0)
return NULL;
else{
p = new nodetype;
p->key = Key[k];
p->left = tree(i,k-1);
p->right = tree(k+1, j);
return p;
}
}
v1에서 시작해서 모든 정점을 돌고 돌아오는 최단거리 경로를 찾는다
모든 가능한 경우의 수 :
: weight,
: 에서 시작해 A에 속한 각 정점을 한 번씩만 사용해 v_1으로 가는 최단 경로 길이
구하고자 하는 값 :
Recursive Property
void travel(int n, const number W[], index P[][], number& minlength){
index i,j,k;
nubmer D[1..n][subset of V-{v1}];
for(i=2; i<=n; i++){
D[i][0] = W[i][1];
for(k=1;k<=n-2;k++)
for(all subsets A ⊆ V-{v_1} containig k vertices)
for(i such that. i!=1 and v_i is not in A){
D[i][A] = min(W[i][j]+D[i][A-{v_j}]);
P[i][A] = j; // minimum 만드는 j
}
D[1][V-{v_1}] = min(W[1][j]+D[1][V-{v_1,v_j}]);
P[1][V-{v_1}] = j // minimum 만드는 j
minlength = D[1][V-{v_i}];
}
}