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

Phương pháp Tham Lam 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 (64.14 KB, 6 trang )

THUẬT TOÁN THAM LAM
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), Tô
màu)
1. Bài toán tam giác số :
int TamGiacThamLam(int a[MAX][MAX],int n,int path[MAX])
{
int tong=0;
int i=1,j=0,k=0;
path[k++]=a[0][0];
tong+=a[0][0];//cập nhật tổng
while(i<n)
{
if(a[i][j]>a[i][j+1])//lựa chọn đường đi
{
path[k++]=a[i][j];//j;//lưu đường đi
tong+=a[i][j];//cập nhật tổng
}
else
{
path[k++]=a[i][j+1];//j+1;//lưu đường đi
tong+=a[i][j+1];//cập nhật tổng
j++;//cập nhật cột
}
i++;//xét hàng tiếp theo
}
return tong;
}
2. Bài toán hái táo :
int HaiTaoThamLam(int a[MAX][MAX],int n,int path[MAX])
{
//tìm cây táo nhiều trái nhất ở hàng dọc đầu tiên


int max=a[0][0],vt=0,soTao=0;
for(int i=1;i<n;i++)
if(max<a[i][0])
{
max=a[i][0];
vt=i;
}
//lưu vị trí xuất phát
int k=0;
path[k++]=vt;
int hangdoc=0,//hàng táo
ddi=vt;//đường đi
soTao+=a[ddi][hangdoc];
while(hangdoc!=n-1)
{
//tìm cây nhiều trái nhất trong 3 cây
ddi=timCayNhieuTrai(a,n,ddi,hangdoc);
//đi đến hàng tiếp theo
hangdoc++;
//lưu đường đi
path[k++]=ddi;
soTao+=a[ddi][hangdoc];
}
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 :
struct MONDO{
unsigned w; //trọng lượng món đồ
int v; //giá trị món đồ
};
//Khai báo biến toàn cục
MONDO a[100];
int n;//số loại món đồ khác nhau
//Hàm đọc dữ liêu từ tập tin
void docfile(char *fname, MONDO a[], int &n)
{
FILE *fp = fopen(fname, "rt");
if (!fp) return;
fscanf(fp, "%d", &n);
for(int i=0; i<n; i++)
fscanf(fp, "%u", &a[i].w);
for(int i=0; i<n; i++)
fscanf(fp, "%d", &a[i].v);
}
void swap(MONDO &a, MONDO &b)

{
MONDO t = a; a = b; b = t;
}
//sắp xếp danh sách các món đồ giảm dần theo đơn giá
void sort(MONDO a[], int n){
for(int i=0; i<n-1; i++)
for(int j=i+1; j<n; j++)
if (a[i].v*1.0/a[i].w < a[j].v*1.0/a[j].w)
swap(a[i],a[j]);
}
//sắp xếp danh sách các món đồ giảm dần theo giá trị
void sort2(MONDO a[], int n){
for(int i=0; i<n-1; i++)
for(int j=i+1; j<n; j++)
if (a[i].v < a[j].v)
swap(a[i],a[j]);
}
//sắp xếp danh sách các món đồ tăng dần theo trọng lượng
void sort3(MONDO a[], int n){
for(int i=0; i<n-1; i++)
for(int j=i+1; j<n; j++)
if (a[i].w > a[j].w)
swap(a[i],a[j]);
}
//Hàm lựa chọn 1 danh sách con các món đồ
//bỏ vừa vào 1 cái túi có sức chứa c
//Sao cho tổng giá trị là lớn nhất
//Chiến thuật: chọn món có đơn giá lớn nhất
//còn bỏ vừa vào túi
//Hàm trả về tổng giá trị của các món được chọn

int Greedy1(MONDO a[], int n, //ds tất cả các món đồ
MONDO chon[], int &nc, //ds các món được chọn
unsigned c) //sức chứa cái túi
{
//B1: Sắp xếp các món đồ giảm dần theo đơn giá
sort(a,n);
int tong=0,i; //tổng giá trị các món được chọn
nc = 0;
do { //chọn bao nhiêu món ko biết, chừng nào đầy thì thôi
i=0;
//B2: Chọn món đgiá lớn nhất có w <= c cho vào túi
while (i<n && a[i].w>c) i++;
if (i<n){ //chọn được
chon[nc++] = a[i];
//B3: Cập nhật lại c và tong
c = c - a[i].w;
tong += a[i].v;
}
}while (i<n);
return tong;
}
//bài toán túi với số lượng đồ hạn chế
int Greedy2(MONDO a[], int n, //ds tất cả các món đồ
MONDO chon[], int &nc, //ds các món được chọn
unsigned c) //sức chứa cái túi
{
//B1: Sắp xếp các món đồ giảm dần theo đơn giá
sort(a,n);
int tong=0,i; //tổng giá trị các món được chọn
nc = 0;

do { //chọn bao nhiêu món ko biết, chừng nào đầy thì thôi
i=0;
//B2: Chọn món đgiá lớn nhất có w <= c cho vào túi
while(i<n)
{
while (i<n && a[i].w>c ) i++;
if (i<n && a[i].SoLuong>0)//chọn được
{
chon[nc++] = a[i];
//B3: Cập nhật lại c và tong
c = c - a[i].w;
tong += a[i].v;
a[i].SoLuong ;
break;
}
i++;
}
}while (i<n);
return tong;
}
//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) :
//Hàm xác định thành phố tiếp theo sẽ đi tới
//từ thành phố hiện tại là c
//(thực chất của bài toán là tìm giá trị min
//của dòng thứ c trong ma trận kề
//nhưng chỉ xét những vị trí có v[i]==0)
//trả về số thứ tự của thành phố tiếp theo tìm được
//nếu không tìm thấy trả về -1
int nextC(int a[][MAX], int n, int v[], int c)

{
int min=10000; //giá trị nhỏ nhất
int vt=-1; //vị trí của giá trị nhỏ nhất
for(int j=0; j<n; j++)
if (a[c][j]<min && v[j]==0){
min = a[c][j];
vt = j;
}
return vt;
}
//Hàm tìm đường đi du lịch qua các thành phố
//(30 phút, 4 điểm)
int timduong(int a[][MAX], int n, //ma trận kề
int tpxp, //thành phố xuất phát
int path[], //lưu đường đi
int &numv, //số tp có thể đi 1<=numv<=n+1
int &tongcp) //tổng chi phí
{
numv = 0;
int c,next;
for(int i=0; i<n; i++) v[i] = 0; //khởi gán tbộ v=0
v[tpxp] = 1;
c = tpxp; //c là thành phố hiện tại
tongcp = 0; //tổng chi phí ban đầu
path[numv++] = c; //đường đi bắt đầu từ tpxp
do{
next = nextC(a,n,v,c); //tìm tp tiếp theo đi được
if (next!=-1){ //có tp để đi
v[next] = 1; //đi sang tp next
path[numv++] = next;//thêm tp đó vào lộ trình

tongcp += a[c][next];//cập nhật lại chi phí
c = next; //next trở thành tp hiện tại
}
}while (numv<n && next!=-1);//dừng khi đi hết, hoặc ko
//đi tiếp được nữa.
if (numv<n) return 0; //ko đi đủ hết các tp
int lastc = path[numv-1];
if (a[lastc][tpxp]<10000) { //kiểm tra đường quay về
path[numv++] = tpxp;
tongcp += a[lastc][tpxp];
return 1;
}
return 0;
}
5. Tô màu :
//Thuật toán tô màu các đỉnh của đồ thị
int tomau(int a[][MAX], int n, int v[])
{
//khởi gán v
for(int i=0; i<n; i++) v[i]=0;
int somau=0;
while (1){
//tìm đỉnh đầu tiên chưa tô (từ trái sang)
int i=0, k;
while (v[i]!=0 && i<n) i++;
if (i>=n) return somau; //tô hết rồi
k = i; //chọn đỉnh k để tô
somau++; //tăng số màu được dùng lên
v[k] = somau; //tô màu cho đỉnh k
//tô màu tất cả các đỉnh ko kề với k

for(; i<n; i++) //chạy tiếp vòng while trên
if (v[i]==0){
int j; //tìm đỉnh j kề với i đã tô màu htại
for(j=0; j<n; j++)
if (v[j]==somau && a[i][j]!=10000)
break;
if (j>=n) v[i] = somau; //nếu ko có thì tô
}
}
}
6. Bài Toán ATM:
//BÀI TOÁN ATM
bool tratien(int kq[], int &n, int k)
{
int t[] = {500,200,100,50,20,10};
n = 0;
while (k>0) {
int i=0;
while (i<6 && t[i]>k) i++;//tìm tờ tiền có thể rút
if (i>=6) return false;
kq[n++] = t[i]; //thêm tờ tiền thứ i vào kq
k -= t[i]; //số tiền cần rút giảm đi
}
return true;
}
//Số tờ tiền của mỗi mệnh giá là hữu hạn
bool tratien2(int kq[], int &n, int k, int soto[])
{
int t[] = {500,200,100,50,20,10};
n = 0;

while (k>0) {
int i=0;
//tìm tờ tiền có thể rút
while (i<6 && (t[i]>k || soto[i]==0)) i++;
if (i>=6) return false;
kq[n++] = t[i]; //thêm tờ tiền thứ i vào kq
k -= t[i]; //số tiền cần rút giảm đi
soto[i] ; //số tờ mệnh giá t[i] giảm đi 1
}
return true;
}

×