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
Trang 1THUẬ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 [MAX][MAX],int ,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 //khoa 5ng giữa
if( [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ổ5 ng đường đi lớn nhấ< t
if(maxT==0) //khở 5i tạo
{
maxT=b[i][j];
vtkt=j;
}
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( [i][vtkt]> a [i][vtkt-1])
path [k++]=vtkt;
else {
path [k++]=vtkt-1;
vtkt ;
} i ;
}
path [k++]=0;
return maxT;
}
Trang 22 Bài toán hái táo :
//quy hoạch động
int HaiTaoQuyHoachDong(int [MAX][MAX],int ,int path [MAX])
{
int b[MAX][MAX]={0},soTao=0,vtkt,k= n -1;
//hàng đấG u tiên ko đổ5 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êG 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 qua 5
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 [MAX][MAX],int ,int ,int )
{
int maxcay= a i ][ j +1],vtm= i
if( [ +1][ j +1]>maxcay && i +1 < n
{
maxcay= a i +1][ j +1];
vtm = i +1;
}
if( [ -1][ j +1]>maxcay && i -1>=0)
{
maxcay= a i -1][ j +1];
Trang 3vtm = i -1;
}
return vtm;
}
3 Bài toán cái túi :
void giai(int [], //ma 5ng chứa tr.lượng các đổG vật
int [], //ma 5ng chứa giá trị các đổG vật
int , //sổ< loại đổG vật
int [][MAX]){ //ma 5ng 2 chiêG u chứa kê< t qua 5
for(int j=0; j<= w ; j++) K [0][j] = 0;
int i,j;
for(i=1; i<= n ; i++) //lấG n lượt xét từng đổG vật
for(j=0; j<= w ; j++) //điêG 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];
}
}
//Tra 5 vêG giá trị lớn nhấ< t có thê5 lấ< y được(chưa viê< t truy vê< t)
int giai2(int [],
int [],
int ,
int ,
int mark []) //đánh dấ< u những món được chọn
{
int L1[MAX]; //dòng đấG u cu 5a ma trận (làm cở sở 5 tính)
int L2[MAX]; //dòng thứ 2 cấG 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ấG n lượt xét từng đổG 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êG n giá trị vào ma 5ng L2 dựa trên ma 5ng 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]);
Trang 4cout<<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 cu 5a void giai
int i=n, tmpw = w;
while (i!=0){
if (K[i][tmpw]!=K[i-1][tmpw]){
cout <<i << " " ; tmpw -= W[i];
} i ;
}
}
4 Bài toán giao hàng (du lịch) :
5 Dãy Fibonaci :
//Cách 1: sư5 dụng quy hoạch động
//Lưu trữ kê<t qua5 trong 1 ma5ng 1 chiêGu có n phấGn tư5 //Độ phức tạp: O(n)
//VD, với n=8, ma5ng 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ư5 sổ< 0
for(int i=3; i<=n; i++)
tmp[i] = tmp[i-1]+tmp[i-2];
return tmp[n];
}
//Cách 2: sư5 dụng quy hoạch động
//Lưu trữ kê<t qua5 trong các (3) biê<n đởn
//Độ phức tạp: O(n)
long F2(int n) {
long t2, t1, t;
Trang 5if (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, ma5ng 1 chiêGu
long GT1(int n) {
if (n<1) return 1; //đởn gia5n
long *F; //ma5ng cấ<p phát động
F = new long[n+1];
if (F==NULL) return 0; //lổVi 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 gia5n
long f1, f;
f1 = 1; //ban đấGu
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 gia5n
long f=1;
for(int i=1; i<=n; i++)
f = f*i;
return f;
}
Trang 67 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++)
{
Trang 7for(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ổ<
//tra5 vêG sổ< cách phấn tích sổ< n thành tổ5ng
long phantichso(int n) {
long F[MAX][MAX];
int m, v;
for(int j=0; j<=n; j++)//khở5i tạo
F[0][j] = 0;
F[0][0] = 1;
for(m=1; m<=n; m++)//sổ< hàng lưu kê<t qua5
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ở5i tạo
F[0][j] = 0;
F[0][0] = 1;
//sổ< hàng chỉ5 còn 2 hàng là [0][v] và [1][v]
for(m=1; m<=n; m++)//sổ< hàng lưu kê<t qua5
{
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];
Trang 8for(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ở5i tạo
F[j] = 0;
F[0] = 1;
//sổ< hàng chỉ5 còn 2 hàng là [0][v] và [1][v]
for(m=1; m<=n; m++)//sổ< hàng lưu kê<t qua5
{
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 :
//ĐấGu vào: dãy a[] có n phấGn tư5
//ĐấGu ra: dãy L[] chứa độ dài các dãy con tăng
// dãy T[] dùng đê5 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 đấGu 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êGn ngược từ cuổ<i lên đấGu dãy
Trang 9for(i=n; i>=0; i )
{ //Tìm vị trí max cu5a ma5ng 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];
Trang 10//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++)
{
Trang 11for(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)
Trang 12if(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 !\
flag=1;
}
tong=0;
Trang 13}
//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 !\
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];
}
Trang 14//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
//return;
flag=1;
}
dem=0;
tong=0;
}
if(flag==0)
printf("\nKhong tim thay vi tri chac chan nao thoa man
}
//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++) {
Trang 15if(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 !\
flag=1;
}
dem=0;
tongi=0;
tongj=0;
}
if(flag==0)
printf("\nKhong tim thay so chac chan nao thoa
}