You are on page 1of 5

#include <stdio.h> : stdio.

h: nơi chứa thông tin để biên dịch cái mình in ra (dữ


liệu sẽ truyền từ file qua stdio.h vào các biến trong chương trình)
#include <stdlib.h>
#define INP "input.inp" define để mình đặt tên (INP là input.inp), ở đây chay INP
tức là chạy input.inp
#define OUT "output.out"
int main() {
fopen: mở file với chế độ đã cho:
r: mở một file để đọc (file đa tồn tại)
w: tạo một file trống để ghi
FILE *fi = fopen(INP, "r"); mở file input.inp
FILE *fo = fopen(OUT, "w"); tạo file output.out
int n, a, b, i, sum = 0; n: tổng số đỉnh, a: đỉnh đầu,b: đỉnh cuối i: đỉnh đang xét
ngắn nhất từ a
// nhap du lieu tu file input
fscanf(fi, "%d%d%d", &n, &a, &b); fscan: đọc tập hợp các ký tự từ file fi, %d:
định dạng kiểu số nguyên, 3 cái %d ứng với 3 cái n,a,b
int G[n][n]; ma trận n hàng n cột
int S[n], Len[n], P[n]; S: đánh dấu các đỉnh i, Len xác định kc ngắn nhất từ a, P
đánh dấu đường đi
// nhap ma tran va tinh gia tri vo cung (sum)
for (i = 0; i < n; i++) xét hàng i nếu i<n i++ tức tăng giá trị i thêm một đơn vị
đến khi = n tức chạy hết i
for (int j = 0; j < n; j++) { xét hàng j nếu j<n j++ tức tăng giá trị j thêm một
đơn vị đến khi = n tức chay j
fscanf(fi, "%d", &G[i][j]);
sum += G[i][j]; độ dài từ i tới j được công dồn
}
// dat vo cung cho tat ca cap canh khong noi voi nhau
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j && G[i][j] == 0) i != j kiểm tra xem i có khác j không, khác nhau
trả về true; G[i][j] == 0 kiểm tra xem kc từ I tới j có bằng 0 không, nếu bằng thì
true
G[i][j] = sum; kc từ i tới j là vô cùng
 Tức là nếu i khác j, mà trong file inp mình nhập chố ij là 0 thì tức là i và j
không nối với nhau, mình cho nó là vô cùng

}
/* Do mang tinh tu G[0][0] nen can giam vi tri di 1 don vi de tinh toan cho phu
hop*/
a--; a- -là giảm a đi một đơn vị (vì mình xét từ điểm 1 nhưng trong này xét từ 0
nên – đi một đơn vị
b--;
for (int i = 0; i < n; i++) {
Len[i] = sum; // khoi tao do dai tu a toi moi dinh la vo cung
S[i] = 0; // danh sach cac diem da xet
P[i] = a; // dat diem bat dau cua moi diem la a
}
Len[a] = 0; // dat do dai tu a -> a la 0
// tim duong di ngan nhat tu 1 dinh den moi dinh khac thi thay bang vong for:
//for (int k = 0; k < n; k++)
while (S[b] == 0) { // trong khi diem cuoi chua duoc xet
for (i = 0; i < n; i++) // tim 1 vi tri ma khong phai la vo cung
if (!S[i] && Len[i] < sum) !S[i]’: chưa xét i, Len[i] < sum: kc từ a tới i k là
vo cùng
break;
 Nếu i chưa được xét và kc từ a tới i k là vô cùng thì dừng lại và thực hiện
lệnh tiếp
// i >=n tuc la duyet het cac dinh ma khong the tim thay dinh b -> thoat
if (i >= n) {
printf("done dijkstra\n");
break;
 i>=n tức đã chạy hết n điểm nhưng không tìm được điểm cuối b thì in ra
done dijkstra ( tức k tìm ra đường ngắn nhất) và thoát
}
for (int j = 0; j < n; j++) { // tim diem co vi tri ma do dai la min
if (!S[j] && Len[i] > Len[j]) {
i = j;
 Nếu (chưa xét j và kc từ a tới i lớn hơn từ a tới j) thì thay i=j
}
}

S[i] = 1; // cho i vao danh sach xet roi


for (int j = 0; j < n; j++) { // tinh lai do dai cua cac diem chua xet
if (!S[j] && Len[i] + G[i][j] < Len[j]) {
Len[j] = Len[i] + G[i][j]; // thay doi len
P[j] = i; // danh dau diem truoc no
 Nếu j chưa xét, mà kc từ a tới i + kc từ i tới j < kc từ a tới j thì thay kc từ a
tới j = kc từ a tới i + kc từ i tới và đánh dấu i là điểm đi trước j
}
}
}

printf("done dijkstra\n");
/* Do ta dang tinh toan tu dinh 0 nen muon hien thi tu dinh 1 thi can dung i + 1 de
phu hop */

printf("start find path\n");


if (Len[b] > 0 && Len[b] < sum) {
fprintf(fo, "Length of %d to %d is %d\n", a + 1, b + 1, Len[b]);
 Nếu kc từ a tới b >0 và kc từ a tới b không phải là vô cực thì xuất ra file
outpu.out điểm đầu, điểm cuối, kc từ a tới b
// truy vet
while (i != a) {
fprintf(fo, "%d <-- ", i + 1);
i = P[i];
 Nói chung cái này là xuất ra cái kết quả kiểu như đi từ 8<-5<-1 vạy á
}
fprintf(fo, "%d", a + 1);
} else {
fprintf(fo, "khong co duong di tu %d den %d\n", a + 1, b + 1);
}
printf("done find path\n");
fclose(fi);
fclose(fo);
printf("done - open file output to see result\n");
return 0;
}
Ràng buộc

V1 nhà máy
V2 khách hàng
Xịj tỉ lệ số hàng hóa gửi đến khách hàng
Fi chi phí cố định
Yj biến nhị phân (0;1)
Tổng 1 là chi phí vận tải
2 là chi phí cố định
Ràng buộc: tỷ lệ hàng hóa gửi kh bằng 1 => gửi hết hàng
Dj nhu cầu khách hàng nhỏ hơn năng lực nhà máy

Dvar : trả về có hoặc không


Dexp đọc cái biến quyết định rồi xuất ra
150 là sức chứa của 1 contener
Subject to ràng buộc
Forall chỉ định các ràng buộc( đây là ràng buộc số 1 2 3)
Dòng
26 xij=1
36 bằng 0 vì khoảng cách lớn hơn 70
Đọc kết quả
-solution là Chi phí cực tiểu
-

You might also like