Tải bản đầy đủ (.docx) (15 trang)

Quy hoạch động trong kĩ thuật lập trình

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (89.66 KB, 15 trang )

THUẬT TOÁN QUY HOẠCH ĐỘNG(điền bảng phương án)
Gồm Có (Bài toán tam giác số , Bài toán hái táo, Bài toán cái túi,Bài toán giao hàng (du
lịch),Dãy Fibonaci , Giai thừa, Phân tích số,Dãy con tăng dài nhất ,Sudoku)
1. Bài toán tam giác số :
int TamGiacQuyHoachDong(int a[MAX][MAX],int n,int path[MAX])
{
int b[MAX][MAX],maxT=0,vtkt,k=0;
b[0][0]=a[0][0];
for(int i=1;i<n;i++)
for(int j=0;j<=i;j++)
{
//quy hoạch
if(j==0 || j==i)//đường biên
if(j==0)
b[i][j]=a[i][j]+b[i-1][j];
else
b[i][j]=a[i][j]+b[i-1][j-1];
else//khoảng giữa
if(a[i-1][j-1]>a[i-1][j])
b[i][j]=a[i][j]+b[i-1][j-1];
else
b[i][j]=a[i][j]+b[i-1][j];
if(i==n-1)//tìm tổng đường đi lớn nhất
if(maxT==0)//khởi tạo
{
maxT=b[i][j];
vtkt=j;
}
else//so sánh
if(maxT<b[i][j])
{


maxT=b[i][j];
vtkt=j;
}
}
inMat(b,n);
//lưu vị trí
int i=n-2;
path[k++]=vtkt;
while(i!=0)
{
//truy vết
if(a[i][vtkt]>a[i][vtkt-1])
path[k++]=vtkt;
else
{
path[k++]=vtkt-1;
vtkt ;
}
i ;
}
path[k++]=0;
return maxT;
}
2. Bài toán hái táo :
//quy hoạch động
int HaiTaoQuyHoachDong(int a[MAX][MAX],int n,int path[MAX])
{
int b[MAX][MAX]={0},soTao=0,vtkt,k=n-1;
//hàng đầu tiên ko đổi
for(int i=0;i<n;i++)

b[i][0]=a[i][0];
//tính các hàng còn lại
for(int j=1;j<n;j++)//hàng dọc
for(int i=0;i<n;i++)//hàng ngang
{
int vtd=timCayNhieuTrai(b,n,i,j-2);//tìm vi trí cây nhiều
trái
b[i][j]=b[vtd][j-1]+a[i][j];//quy hoạch
if(j==n-1)
if(soTao==0){
soTao=b[i][j];
vtkt=i;
}
else{
if(soTao<b[i][j]){
soTao=b[i][j];
vtkt=i;
}
}
}
//ma trận kết quả
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%2d ",b[i][j]);
printf("\n");
}
//đường đi
int c=4;
path[k ]=vtkt;

while(c!=0)
{
int vtcay=timCayNhieuTrai(b,n,vtkt,c-2);
path[k ]=vtcay;
vtkt=vtcay;
c ;
}
return soTao;
}
int timCayNhieuTrai(int a[MAX][MAX],int n,int i,int j)
{
int maxcay=a[i][j+1],vtm=i;
if(a[i+1][j+1]>maxcay && i+1 <n)
{
maxcay=a[i+1][j+1];
vtm = i+1;
}
if(a[i-1][j+1]>maxcay && i-1>=0)
{
maxcay=a[i-1][j+1];
vtm = i-1;
}
return vtm;
}
3. Bài toán cái túi :
//Bài toán: Bài toán cái túi (mỗi loại 1 món đồ)
void giai(int W[], //mảng chứa tr.lượng các đồ vật
int V[], //mảng chứa giá trị các đồ vật
int n, //số loại đồ vật
int w, //sức chứa của cái túi

int K[][MAX]){ //mảng 2 chiều chứa kết quả
//điền toàn bộ dòng 0 của ma trận K bằng giá trị 0
for(int j=0; j<=w; j++) K[0][j] = 0;
int i,j;
for(i=1; i<=n; i++) //lần lượt xét từng đồ vật
for(j=0; j<=w; j++) //điền giá trị các ô trên dòng i
{
//gán bằng với giá trị trước khi xét món i
K[i][j] = K[i-1][j];
//Nếu chọn món i có lợi hơn
if (j>=W[i] && K[i][j]<K[i-1][j-W[i]]+V[i])
K[i][j] = K[i-1][j-W[i]]+V[i];
}
}
//Trả về giá trị lớn nhất có thể lấy được(chưa viết truy vết)
int giai2(int W[],
int V[],
int n,
int w,
int mark[]) //đánh dấu những món được chọn
{
int L1[MAX]; //dòng đầu của ma trận (làm cơ sở tính)
int L2[MAX]; //dòng thứ 2 cần tính toán
//tự code nhé
int tang=0;
for(int j=0; j<=w; j++) L1[j] = 0;
int i,j;
for(i=1; i<=n; i++) //lần lượt xét từng đồ vật
{
//chưa chọn món nào hết

for(int j=0; j<=w; j++) mark[j] = 0;
tang=0;
for(j=0; j<=w; j++) //điền giá trị vào mảng L2 dựa trên mảng L1
{
//gán bằng với giá trị trước khi xét món i
L2[j] = L1[j];
//Nếu chọn món i có lợi hơn
if (j>=W[i] && L2[j]<L1[j-W[i]]+V[i])
{
L2[j] = L1[j-W[i]]+V[i];
}
}
for(int ka=0;ka<=w;ka++)
{
L1[ka]=L2[ka];
printf("%3d",L1[ka]);
}
cout<<endl;
}
Void main()
{
giai(W,V,n,w,K);
for(int e=1;e<=n;e++)
{
cout<<e<<":";
for(int j=0;j<=w;j++)
printf("%3d",K[e][j]);
cout<<endl;
}
cout <<"Gia tri lon nhat voi w="<<w<<" la: " <<K[n][w];

cout <<"\nDanh sach cac mon duoc chon:\n";
//truy vết của void giai
int i=n, tmpw = w;
while (i!=0){
if (K[i][tmpw]!=K[i-1][tmpw]){
cout <<i <<" ";
tmpw -= W[i];
}
i ;
}
}
//Bài toán: Bài toán cái túi (số lượng món đồ ko giới hạn)
4. Bài toán giao hàng (du lịch) :
5. Dãy Fibonaci :
//Cách 1: sử dụng quy hoạch động
//Lưu trữ kết quả trong 1 mảng 1 chiều có n phần tử
//Độ phức tạp: O(n)
//VD, với n=8, mảng tmp: x 1 1 2 3 5 8 13 21
long F1(int n) {
long tmp[MAX];
tmp[1] = tmp[2] = 1; //không dùng ptử số 0
for(int i=3; i<=n; i++)
tmp[i] = tmp[i-1]+tmp[i-2];
return tmp[n];
}
//Cách 2: sử dụng quy hoạch động
//Lưu trữ kết quả trong các (3) biến đơn
//Độ phức tạp: O(n)
long F2(int n) {
long t2, t1, t;

if (n<=2) return 1;
t2 = t1 = 1;
for(int i=3; i<=n; i++)
{
t = t2+t1;
t2 = t1;
t1 = t;
}
return t;
}
6. Giai thừa :
//Dùng quy hoạch động, mảng 1 chiều
long GT1(int n) {
if (n<1) return 1; //đơn giản
long *F; //mảng cấp phát động
F = new long[n+1];
if (F==NULL) return 0; //lỗi cấp phát
F[0] = 1;
//Tính GT(n)
for(int i=1; i<=n; i++)
F[i] = i*F[i-1];
long t = F[n];
delete F;
return t;
}
//Quy hoạch động, dùng 2 biến
long GT2(int n) {
if (n<1) return 1; //đơn giản
long f1, f;
f1 = 1; //ban đầu

for(int i=1; i<=n; i++){
f = f1*i;
f1 = f;
}
return f;
}
//Quy hoạch động, dùng 1 biến
long GT3(int n) {
if (n<1) return 1; //đơn giản
long f=1;
for(int i=1; i<=n; i++)
f = f*i;
return f;
}
7. Tổ hợp :
int TinhToHop1D(int a[MAX],int n,int k)
{
for(int i=0;i<n;i++)
a[i]=0;
int tam,tam1;
a[0]=1;
//in
for(int q=0;q<=n;q++)
printf("%4d ",a[q]);
printf("\n");
//tính toán
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
if(j==1){
tam=a[j];

a[j]=a[j]+a[j-1];
}
else{
tam1=a[j];
a[j]=a[j]+tam;
tam=tam1;
}
}
//in
for(int q=0;q<=n;q++)
printf("%4d ",a[q]);
printf("\n");
}
return a[k];
}
int TinhToHop2D(int a[MAX],int b[MAX],int n,int k)
{
for(int i=0;i<=n;i++)
a[i]=0;
a[0]=1;
//in KQ
for(int q=0;q<=n;q++)
printf("%4d ",a[q]);
printf("\n");
//
for(int i=1;i<=n;i++)
{
b[0]=1;
for(int j=1;j<=i;j++)
b[j]=a[j]+a[j-1];

for(int ka=0;ka<=n;ka++)
a[ka]=b[ka];
//in KQ
for(int q=0;q<=n;q++)
printf("%4d ",a[q]);
printf("\n");
}
return a[k];
}
8. Phân tích số :
//Bài toán phân tích số
//trả về số cách phân tích số n thành tổng
long phantichso(int n) {
long F[MAX][MAX];
int m, v;
for(int j=0; j<=n; j++)//khởi tạo
F[0][j] = 0;
F[0][0] = 1;
for(m=1; m<=n; m++)//số hàng lưu kết quả
for(v=0; v<=n; v++)//số cột
if (v<m)
F[m][v] = F[m-1][v];
else
F[m][v] = F[m-1][v] + F[m][v-m];
return F[n][n];
}
long QHD2Dphantichso(int n)
{
long F[2][MAX];
int m,v;

for(int j=0; j<=n; j++)//khởi tạo
F[0][j] = 0;
F[0][0] = 1;
//số hàng chỉ còn 2 hàng là [0][v] và [1][v]
for(m=1; m<=n; m++)//số hàng lưu kết quả
{
for(v=0; v<=n; v++)//số cột
{
if (v<m)
F[1][v] = F[0][v];
else
F[1][v] = F[0][v] + F[1][v-m];
}
for(int k=0;k<=n;k++)
F[0][k]=F[1][k];
}
return F[1][n];
}
long QHD1Dphantichso(int n)
{
long F[MAX];
int m,v;
for(int j=0; j<=n; j++)//khởi tạo
F[j] = 0;
F[0] = 1;
//số hàng chỉ còn 2 hàng là [0][v] và [1][v]
for(m=1; m<=n; m++)//số hàng lưu kết quả
{
for(v=0; v<=n; v++)//số cột
{

if (v<m)
F[v] = F[v];
else
F[v] = F[v] + F[v-m];
}
for(int k=0;k<=n;k++)
F[k]=F[k];
}
return F[n];
}
9. Dãy con tăng dài nhất :
//Đầu vào: dãy a[] có n phần tử
//Đầu ra: dãy L[] chứa độ dài các dãy con tăng
// dãy T[] dùng để truy vết
void daytang(int a[], int n, int L[], int T[])
{
//Định nghĩa giá trị VÔ CÙNG
int MAX_INT;
MAX_INT = (int)pow(2.0,31)-1; //2^31-1
//Chèn thêm giá trị -VC và +VC vào đầu và cuối dãy a
memmove(a+1,a,n*sizeof(int));
a[0] = -MAX_INT;
a[n+1] = MAX_INT;
//inm(a,n+2);
int i,j,jmax;
L[n+1] = 1; //điền ngược từ cuối lên đầu dãy
for(i=n; i>=0; i )
{ //Tìm vị trí max của mảng L[] từ i+1 đến n+1,
//có a[j]>a[i]
jmax = n+1;

for(j=i+1; j<=n+1; j++)
if (a[j]>a[i] && L[j]>L[jmax])
jmax = j;
//ghi nhận lại giá trị cho L[i] và T[i]
L[i] = L[jmax]+1;
T[i] = jmax;
}
}
10. Sudoku:
//hamkiem tra dong
int ktdong(int a[][MAX], int k)
{
for(int i=0; i<8; i++)
for(int j=i+1; j<9; j++)
if (a[k][i] && a[k][i]==a[k][j])
return 1;
return 0;
}
//kiem tra cot
int ktcot(int a[][MAX], int k)
{
for(int i=0; i<8; i++)
for(int j=i+1; j<9; j++)
if (a[i][k] && a[i][k]==a[j][k])
return 1;
return 0;
}
//kiem tra vung 3x3 thu k
int kt3x3(int a[MAX][MAX],int k)
{

int m[9];//mang phu
int d=3*(k/3)+1,c=3*(k%3)+1;//tinh vi tri o giua vung 3x3
int v=0;
//chuyen vung 3x3 thanh mang 1 chieu
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++)
{
m[v++]=a[d+i][c+j];
}
//kiem tra vi pham
for( i=0; i<8; i++)
for(int j=i+1; j<9; j++)
if (m[i] && m[i]==m[j])
return 1;
return 0;
}
// tim dong co it o trong nhat
int DongItOTrongNhat(int a[MAX][MAX])
{
int dem=0,vt=-1,min=-1;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(a[i][j]==0)
dem++;
}
if(dem>=1)
if(min==-1)
{

min=dem;
vt=i;
}
else
if(dem<min)
{
min=dem;
vt=i;
}
dem=0;
}
return vt;
}
//tim cot co it o trong nhat
int CotItOTrongNhat(int a[MAX][MAX])
{
int dem=0,vt=-1,min=-1;
for(int j=0;j<9;j++)
{
for(int i=0;i<9;i++)
{
if(a[i][j]==0)
dem++;
}
if(dem>=1)
if(min==-1)
{
min=dem;
vt=j;
}

else
if(dem<min)
{
min=dem;
vt=j;
}
dem=0;
}
return vt;
}
//tim vung 3x3 co it o trong nhat
int Vung3x3ItOTrongNhat(int a[MAX][MAX])
{
int m[9];//mang phu
int dem=0,min=-1,vt=-1;
for(int k=0;k<9;k++)
{
int d=3*(k/3)+1,c=3*(k%3)+1;//tinh vi tri o o gius vung 3x3
int v=0;
//chuyen vung 3x3 thanh mang 1 chieu
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++)
{
m[v++]=a[d+i][c+j];
}
//dem so o so 0 trong mang 1 chieu hay vung 3x3
for( i=0;i<9;i++)
{
if(m[i]==0)
dem++;

}
//tim min
if(dem>=1)
if(min==-1)
{
min=dem;
vt=k;
}
else
if(min>dem)
{
min=dem;
vt=k;
}
dem=0;
}
return vt;
}
void TimOTrongDienThem(int a[MAX][MAX],int &vti,int &vtj,int &vtv,
int &soD)
{
int flag=0;
vtv=-1;
//tim o cac dong
int dem=0,vt=-1,min=-1,tong=0,nho=-1;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
tong+=a[i][j];

if(a[i][j]==0)
{
dem++;
nho=j;
}
}
if(dem==1)//chi co 1 o trong
{
soD=45-tong;
vti=i;
vtj=nho;
//return;
printf("\nVi tri [%d,%d] dien chu so
%d !\n",vti,vtj,soD);
flag=1;
}
tong=0;
dem=0;
}
//tim o cac cot
dem=0;vt=-1;min=-1,nho=-1;
for(int j=0;j<9;j++)
{
for(int i=0;i<9;i++)
{
tong+=a[i][j];
if(a[i][j]==0)
{
dem++;
nho=i;

}
}
if(dem==1)
{
soD=45-tong;
vti=nho;
vtj=j;
//return;
printf("\nVi tri [%d,%d] dien chu so
%d !\n",vti,vtj,soD);
flag=1;
}
dem=0;
tong=0;
}
//tim tren vung 3x3
int m[MAX];//mang phu
dem=0;
for(int k=0;k<9;k++)
{
int d=3*(k/3)+1,c=3*(k%3)+1;//tinh vi tri o giua vung 3x3
int v=0,luuvt=-1;
tong=0;
//chuyen vung 3x3 thanh mang 1 chieu
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++)
{
m[v++]=a[d+i][c+j];
}
//dem so o so 0 trong mang 1 chieu hay vung 3x3

for( i=0;i<9;i++)
{
tong+=m[i];//timtong tat cac so trong vung 3x3
if(m[i]==0)
{
dem++;
luuvt=i;
}
}
if(dem==1)
{
soD=45-tong;
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++)
{
if(a[d+i][c+j]==0)
{
vti=d+i;
vtj=c+j;
vtv=k;
}
}
printf("\nVi tri [%d,%d] vung %d dien chu so
%d !\n",vti,vtj,vtv,soD);
//return;
flag=1;
}
dem=0;
tong=0;
}

if(flag==0)
printf("\nKhong tim thay vi tri chac chan nao thoa
man !!!\n");
}
//tim so co the dien them
void SoCoTheDienThem(int a[MAX][MAX],int &vti,int &vtj,int &vtv, int
&soD)
{
int dem=0,tongi=0,tongj=0,flag=0;
for(int so=1;so<10;so++)
{
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
{
if(a[i][j]==so)
{
tongi+=i;//tinh tong cac hang
tongj+=j;//tinh tong cac cot
dem++;//dem so chu so = so
}
}
if(dem==8)
{
soD=so;
vti=36-tongi;
vtj=36-tongj;
//return;
printf("\nVi tri [%d,%d] dien chu so
%d !\n",vti,vtj,soD);
flag=1;

}
dem=0;
tongi=0;
tongj=0;
}
if(flag==0)
printf("\nKhong tim thay so chac chan nao thoa man !!!\n");
}

×