BÁO CÁO THỰC HÀNH, TRÍ TUỆ NHÂN TẠO,KHOA CÔNG NGHỆ THÔNG TIN, ĐH BÁCH KHOA ĐÀ NẴNG
Trang 1TRƯỜNG ĐẠI HỌC BÁCH KHOA
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO THỰC HÀNH
TRÍ TUỆ NHÂN TẠO
Giáo viên : Võ Đức Hoàng Sinh viên thực hiện : NGUYỄN HẢI QUẢNG
Đà Nẵng, 10/2013
Trang 2I Trò chơi 8 quân cờ (Cờ ta canh):
1 Bài toán:
Tám (8) quân cờ được chỉ ra trong hình, gồm một bảng kích thước 3x3với 8 quân
cờ dược đánh số từ 1 đến 8 và một ô trống Một quân cờ đứng cạnh ô trống có thểđivào ô trống Mục tiêu là luôn luôn tiến tới vị trí các quân cờ như ở trong hình bênphải (trạng thái đích)
Trạng thái đầu Trạng thái đích
Hãy trình bày thuật toán và viết chương trình demo để di chuyển các quân cờ saocho số bước di chuyển là thấp nhất (tối ưu) Dữ liệu được đọc từ file là ma trận vuông3x3
Tạo ra 2 mảng Open và Close
Mảng open chứa trạng thái chưa xét và được sắp xếp theo thứ tự lớn dần F(n)Mảng Close chứa các trạng thái được đưa vào đường đi
Mỗi khi lấy trạng thái nhỏ nhất trong mảng open minOpen bỏ sang mảng closethì thêm các trạng thái vừa được sinh ra từ trạng thái minOpen vào mảng open rồi sắpxếp lại theo thứ tự lớn dần F(n)
Cứ như vậy cho đến khi H(n) = 0 ( trạng thái đích )
static boolean result;
static LinkedList<State> stateQueue;
1 2 3
4 5 6
7 8
Trang 3public static void main(String[] args)
{
result=false;
State startState = new State(null);
State finalState = new State(null);
Trang 4BufferedReader br = new BufferedReader(fr);
for (int i=0;i<9;i++)
Trang 7public static StateNode firstNode;
public static StateNode lastNode;
Trang 8
StateNode tmpNode = firstNode;
while (tmpNode!=null && !result)
Trang 9nguyên dương N cho trước Với số bắt đầu là 1, ai viết được số N trước thì xem nhưthắng.
Xem như máy là người đi sau Trình bày thuật toán và viết chương trình mô tả tròchơi sao cho khả năng thắng của máy cao Dữ liệu được đọc từ bàn phím
Trường hợp thứ 2 : N là số chẵn Vì khi a > N/2 thì chỉ có thể đi a + 1( Nếu đi 2a sẽ vượt quá N) nên máy muốn thắng thì phải luôn đi vào số chẵn khi a >N/2 Vậy khi đến lượt máy nếu 2a > N/2 thì máy sẽ đi 2a để chiến thắng Ngược lại thì
đi a + 1 để giảm khả năng thắng của người ( Nếu đi 2a < N/2 Đến lượt của người đi2a sẽ có khả năng > N/2 cao) Ở trường hợp này thì máy không luôn luôn thắng Vìnếu người cũng tính được đi vào 2a > N/2 để chiến thắng thì người cũng sẽ làm cácbước tương tự như máy Nhưng người có lợi thế hơn là từ đầu đã đi vào số chẵn
} catch (NumberFormatException | IOException e1) {
// TODO Auto-generated catch blocke1.printStackTrace();
}while(a!=n){
try {
Trang 10} catch (NumberFormatException | IOException e) {
// TODO Auto-generated catch blocke.printStackTrace();
}}}
public static void tinh()
if(a==n) System.out.println("Computer win");
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stubnhap();
tự trên máy A máy B máy C
Trình bày thuật toán và viết chương trình mô tả sao cho tổng thời gian gia cônghoàn thành n chi tiết là thấp nhất (tối ưu) Dữ liệu được đọc từ file có dạng như sau:DULIEU.INP
n //số chi tiết cần gia công
Trang 11J1A, J2A, , JnA //thời gian gia công các chi tiết trên máy A
J1B, J2B, , JnB //thời gian gia công các chi tiết trên máy B
J1C, J2C, , JnC //thời gian gia công các chi tiết trên máy CKết quả xuất ra là thứ tự các công việc
2 Thuật toán:
Bài toán gia công với 3 máy A, B, C.
Đối với bài toán có 2 máy gia công A, B Thời gian gia công các chi tiết Ji trênmáy A là TAi ( i = 1…n), thời gian gia công các chi tiết Ji trên máy B là TBi ( i = 1…
n ) Ta phân các chi tiết làm 2 nhóm
Nhóm thứ 1 : Có các chi tiết Ji thỏa mãn TAi < TBi
Nhóm thứ 2 : Có các chi tiết Ji thỏa mãn TAi > TBi
Các chi tiết Ji có TAi = TBi phân vào nhóm nào cũng được
Sắp xếp các chi tiết nhóm 1 theo chiều tăng TAi, và sắp xếp các chi tiết nhóm
2 theo chiều giảm TBi
Nối nhóm 2 vào nhóm 1 ta sẽ có trình tự gia công các chi tiết
Lịch gia công tối ưu trên 3 máy A, B, C trùng với lịch gia công tối ưu trên 2máy, ta chia làm 2 máy : máy thứ 1 với thời gian TAi + TBi, máy thứ 2 với thời gianTBi + TCi Phân làm 2 nhóm
Nhóm thứ 1 : Có các chi tiết Ji thỏa mãn TAi + TBi < TBi + TCi
Nhóm thứ 2 : Có các chi tiết Ji thỏa mãn TAi + TBi > TBi + TCi
Các chi tiết Ji có TAi + TBi= TBi + TCi phân vào nhóm nào cũng được
Sắp xếp các chi tiết nhóm 1 theo chiều tăng TAi, và sắp xếp các chi tiết nhóm
2 theo chiều giảm TBi
Nối nhóm 2 vào nhóm 1 ta sẽ có trình tự gia công các chi tiết
static int[][] array;
static int[] group1, group2;
public static void load() throws IOException
{
try {
File f = new File("input.txt");
Trang 12FileReader fr = new FileReader(f);
BufferedReader bf = new BufferedReader(fr);
public static void calculate()
{
group1 = new int[n];
group2 = new int[n];
int i = 0, x = 0, y = 0;
for(i = 0,x = 0, y = 0; i < n; i ++){
if(array[0][i] + array[1][i] < array[1][i] + array[2][i]){
group1[x] = i;
x++;
}else {
group2[y] = i;
y++;
}}
Trang 13public static void dockinggroup2(int count)
public static int readbuffer(BufferedReader bf) throws IOException
{
int result = 0;
int i = bf.read();
while (!isNumber(i)) i=bf.read();
do {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stubload();
calculate();
}
}
Trang 14IV Bài toán người du lịch:
1 Bài toán:
Một người khách du lịch muốn đi thăm n thành phố được đánh số từ 1 n và quaylại thành phố xuất phát Mạng lưới giao thông giữa n thành phố này là hai chiều vàđược cho bởi ma trận A[i,j] trong đó A[i,j]=1 nếu có đường đi từ thành phố i đến thànhphố j, A[i,j]=0 trong trường hợp ngược lại
Hãy thiết lập lộ trình cho người khách hay thông báo không tồn tại lời giải Dữ liệuđược đọc từ file có dạng như sau:
DULIEU.INP
Dòng 1: Ghi số nguyên n (n<=20)
Dòng i+1 (1<=i<=n) ghi n số nguyên không âm (0 hoặc 1)
Kết quả xuất ra chu trình đường đi (Chu trình HAMILTON)
2 Thuật toán:
3 Chương trình:
V Bài toán hệ thống dây điện:
1 Bài toán:
Một công ty cần thay toàn bộ hệ thống dây điện cho N phòng làm việc Cho biết sơ
đồ mạng lưới điện hiện có của n căn phòng được biểu diễn bằng ma trận A[i,j] trong
đó A[i,j] chính là độ dài của dây điện nối giữa 2 phòng i và j (A[i,j]=A[j,i], A[i,j]=0nếu không có (không thể) dây nối giữa phòng i và j) Hãy lập trình tính độ dài của dâydẫn cần sử dụng sao cho cả N phòng dều có điện và số lượng này là ít nhất
Dữ liệu được đọc từ file có N+1 dòng dạng như sau: DULIEU.INP
Dòng 1: Ghi số nguyên N
Dòng i+1 (1<=i<=N) ghi N số nguyên A[i,1] A[i,2] A[i,N]
Các số ghi trên 1 dòng cách nhau ít nhất 1 dấu cách
Kết quả xuất ra màn hình cách nối và tổng độ dài nhỏ nhất
+ Có bao nhiêu chữ số trong M là chữ số trong S nhưng vị trí xuất hiện của mỗichữ số đó là sai?
+ Có bao nhiêu chữ số trong M là chữ số trong S và đồng thời vị trí xuất hiện củamỗi chữ số đều đúng?
Yêu cầu: Hãy hiện lên màn hình các số máy dự đoán và nói mỗi số đó nhận 2
câu trả lời từ bàn phím của cậu bé cho đến khi được số đúng như cậu bé nghĩ (Số lần
dự đoán không quá 6 lần)
Trang 15Ví dụ: Số cần tìm là 5436
1234
Đúng số - Đúng vị trí : 1 Đúng số - Sai vị trí : 1
2156
Đúng số - Đúng vị trí : 1 Đúng số - Sai vị trí : 1
1416
Đúng số - Đúng vị trí : 2 Đúng số - Sai vị trí : 0
5436
Đúng số - Đúng vị trí : 4 Đúng số - Sai vị trí : 0
Trong ngày sinh nhật Tom và Jerry nhận được N đồ chơi (N<=40) Trên đồ chơi i
có giá tiền là Xi Hai anh em quyết định mỗi người phải có trách nhiệm bảo quản 1phần số quà và phân chia sao cho chênh lệch tổng giá trị tiền đồ chơi mà mỗi ngườiphải bảo quản là ít nhất Hãy giúp Tom bà Jerry phân chia trách nhiệm Dữ liệu đọc từfile text có dạng sau:
Dòng 1 : ghi số nguyên dương N
Dòng 2 : Ghi N số nguyên dương tương ứng với giá trị N đồ vật
File dữ liệu đầu vào: GRAPH.INP có cấu trúc
Trang 16Nếu đề bài cho là một đồ thị nhỏ,đơn giản thì ta cố thử theo mọi phương
án để có thể đi đến một lời giải tối ưu.Nhưng đối với bài toán lớn,phức tạp thì cách làm bài toán này sẽ tốn rất nhiều thời gian và có thể không tìm được lời giải,trên thực tế thì khó có thể chấp nhận được.
Vì vậy cần có giải pháp tối ưu hơn.Trong đó tiêu biểu là giải thuật heuristic hay người ta vẫn gọi la thuật toán “háu ăn” (Greedy Algorithm).Một giải thuật heuristic hợp lý đối với bài toán tô màu cho đồ thị được mô tả như sau: Đầu tiên ta cố tô màu cho các đỉnh nhiều hết mức có thể bằng một màu.Với
Trang 17Để tô màu cho các đỉnh với màu mới,ta làm như sau:
1.Chọn một đỉnh chưa được tô màu nào đó và tô cho nó màu mới 2.Tìm trong danh sách các đỉnh chưa được tô màu,với mỗi đỉnh đó
ta xác định xem có một cung nào nối nó với một đỉnh đã được tô bằng màu mới chưa.Nếu chưa có thì tô đỉnh đó bằng màu mới.
Cách tiếp cận này được gọi là “háu ăn” vì nó thực hiện tô màu một đỉnh nào đó mà nó có thể tô được,không hề chú ý đến tình thế bất lợi có thể xuất hiện khi làm điều đó
cacDinh =new Dinh[soDinh];
}publicvoid TaoDoThi(){
try{ File inputFile = new File("E:\\input.txt");
FileInputStream fis = new FileInputStream(inputFile);
if((c!=13)&&(c!=10)&&(c!=32))
Trang 18if(i<soDinh){
tam=fis.read();
if((tam!=13)&&(tam!=10)&&(tam!=32)){
tam=tam-48;
if(j<cacDinh[i].dinhKe.soDinhKe){
cacDinh[i].dinhKe.tenDinhKe[j]=tam;
j++;
}
}} }
i++;
} } fis.close();
int tam1=0, tam2=0;
for (int i = 0; i < dinh.dinhKe.soDinhKe; i++){
//Lay chi so cuadinhkevoidinh tam1 =dinh.dinhKe.tenDinhKe[i]-1;
tam2 = cacDinh[tam1].soMauCam++;
cacDinh[tam1].cacMauCam[tam2] = dinh.mauDaTo;
Trang 19publicboolean KiemTraMauCam(Dinh dinh, int mau)
{
if ((cacDinh[i].mauDaTo == 0) &&(KiemTraMauCam(cacDinh[i],somau) == false))
{ cacDinh[i].mauDaTo = somau;
dem++;
CamMau(cacDinh[i]);
for (int j = 0; j < soDinh; j++)
{int co=0;
for(int k=0;k<cacDinh[i].dinhKe.soDinhKe;k++) {
if (j+1 ==cacDinh[i].dinhKe.tenDinhKe[k]){
co = 1;
break;
} }
if (co == 0 && cacDinh[j].mauDaTo ==0) {
if ((KiemTraMauCam(cacDinh[j],somau))== false)
{ cacDinh[j].mauDaTo = somau;
dem++;
Trang 20CamMau(cacDinh[j]);
} }}
somau++;
}else dem++;
}}
for(int i=0;i<cacDinh.length;i++) {
System.out.println("Dinh "+(i+1)+" Co Mau
"+cacDinh[i].mauDaTo);
}
}publicvoid Luu()
{
try{
File outputFile = new File("E:\\output.txt");
FileWriter f=new FileWriter(outputFile);
for(int i=0;i<cacDinh.length;i++) {
f.write("Dinh"+(i+1));
f.write("Co Mau:"+cacDinh[i].mauDaTo);
f.write("\n");
} f.close();
Trang 21IX Người lái đò:
Ký hiệu bờ sông mà sói, dê, bắp cải và bác lái đò đang đứng là 1, bờ sông bên kia
là 2 Hãy viết chương trình giải quyết bài toán trên
2 Thuật toán:
- Bài toán có hai trạng thái:
Trạng thái bờ trái {Dê, Bắp cải, Sói, Người lái đò}
Trạng thái bờ phải {Dê, Bắp cải, Sói, Người lái đò}
- Mỗi trạng thái có một cách thay đổi:
Trạng thái bờ trái: Di chuyển qua bờ phải
Trạng thái bờ phải: Di chuyển về lại bờ trái
- Mỗi cách thay đổi trạng thái sẽ có cách thay đổi cụ thể:
Di chuyển thầy tu hoặc quỷ qua bờ phải có ba trường hợp thay đổitrạng thái:
Đưa 2 thầy tu qua bờ phải
Đưa 2 quỷ qua bờ phải
Đưa 1 thầy tu hoặc 1 quỷ qua bờ phải
Di chuyển thầy tu hoặc quỷ về lại bờ trái có hai trường hợp thay đổi trạng thái:
Đưa 1 quỷ về bờ trái
Đưa 1 thầy tu và 1 quỷ về bờ trái
- Mỗi lần thực hiện thay đổi trạng thái thì cần phải kiểm tra trạng thái đó có
thay đổi đúng hay không?
Số thầy tu phải lớn hơn bằng số quỷ hoặc số thầy tu bằng 0 ở mỗi trạng thái
- Như vậy, bài toán này sẽ thực hiện theo thuật toán Best-first Search để tìm
Trang 22// Initiallize Goat = 1, Cabbage = 2, Wolf = 3, Ferryman = 4.
// Goat, Cabbage and Wolf are in brink left
bool check(int a, int b, int c, int d) {
if((a == 1 && b == 2 && c == 3 && d == 0)
|| (a == 1 && b == 2 && c == 0 && d == 4)
|| (a == 1 && b == 0 && c == 3 && d == 4)
|| (a == 0 && b == 2 && c == 3 && d == 4)
|| (a == 0 && b == 2 && c == 3 && d == 0)
|| (a == 1 && b == 0 && c == 0 && d == 4)
|| (a == 0 && b == 2 && c == 0 && d == 4)
|| (a == 0 && b == 0 && c == 3 && d == 4)
|| (a == 1 && b == 0 && c == 0 && d == 0)
|| (a == 0 && b == 2 && c == 0 && d == 0)
|| (a == 0 && b == 0 && c == 3 && d == 0 && count == 2)
|| (a == 0 && b == 0 && c == 0 && d == 0)
|| (a == 1 && b == 2 && c == 3 && d == 4))
tempRight[0] = brinkRight[0]; tempRight[1] = brinkRight[1];
tempRight[2] = brinkRight[2]; tempRight[3] = brinkRight[3];
switch(i) {// Goat + Ferryman pass over
case 0: {
tempLeft[0] -= 1; tempRight[0] += 1;
Trang 23}// Cabbage + Ferryman pass over
}if(check(tempLeft[0], tempLeft[1], tempLeft[2], tempLeft[3])
&& check(tempRight[0], tempRight[1], tempRight[2], tempRight[3])) {
count++;
brinkLeft[0] = tempLeft[0]; brinkLeft[1] = tempLeft[1];
brinkLeft[2] = tempLeft[2]; brinkLeft[3] = tempLeft[3];
brinkRight[0] = tempRight[0]; brinkRight[1] = tempRight[1];brinkRight[2] = tempRight[2]; brinkRight[3] = tempRight[3];switch(i) {
cout << count << " Cabbage pass over: Left
->>> Right." << endl;
break;
}case 2: {
cout << count << " Wolf pass over: Left ->>>Right." << endl;
break;
}default: break;
}break;
}
Trang 24tempRight[0] = brinkRight[0]; tempRight[1] = brinkRight[1];
tempRight[2] = brinkRight[2]; tempRight[3] = brinkRight[3];
switch(i) {// Ferryman comeback again
case 0: {
tempLeft[3] += 4; tempRight[3] -= 4;
break;
}// Goat comeback again
}if(check(tempLeft[0], tempLeft[1], tempLeft[2], tempLeft[3])
&& check(tempRight[0], tempRight[1], tempRight[2], tempRight[3])) {
count++;
brinkLeft[0] = tempLeft[0]; brinkLeft[1] = tempLeft[1];
brinkLeft[2] = tempLeft[2]; brinkLeft[3] = tempLeft[3];
brinkRight[0] = tempRight[0]; brinkRight[1] = tempRight[1];
Trang 25cout << count << " Goat comeback: Right
->>> Left." << endl;
break;
}case 2: {
cout << count << " Cabbage comeback: Right
->>> Left." << endl;
break;
}case 3: {
cout << count << " Wolf comeback: Right
->>> Left." << endl;
break;
}default: break;
}break;
}}
if(brinkRight[0] && brinkRight[1] && brinkRight[2] && brinkRight[3]) {
cout << endl << " -COMPUTER
Trang 26}display();
Trang 272 Thuật toán:
- Bài toán có hai trạng thái:
Trạng thái bờ trái {số thầy tu, số quỷ}
Trạng thái bờ phải {số thầy tu, số quỷ}
- Mỗi trạng thái có một cách thay đổi:
Trạng thái bờ trái: Di chuyển thầy tu hoặc quỷ qua bờ phải
Trạng thái bờ phải: Di chuyển thầy tu hoặc quỷ về lại bờ trái
- Mỗi cách thay đổi trạng thái sẽ có cách thay đổi cụ thể:
Di chuyển thầy tu hoặc quỷ qua bờ phải có ba trường hợp thay đổitrạng thái:
Đưa 2 thầy tu qua bờ phải
Đưa 2 quỷ qua bờ phải
Đưa 1 thầy tu hoặc 1 quỷ qua bờ phải
Di chuyển thầy tu hoặc quỷ về lại bờ trái có hai trường hợp thay đổi trạng thái:
Đưa 1 quỷ về bờ trái
Đưa 1 thầy tu và 1 quỷ về bờ trái
- Mỗi lần thực hiện thay đổi trạng thái thì cần phải kiểm tra trạng thái đó có
thay đổi đúng hay không?
Số thầy tu phải lớn hơn bằng số quỷ hoặc số thầy tu bằng 0 ở mỗi trạng thái
- Như vậy, bài toán này sẽ thực hiện theo thuật toán Best-first Search để tìm
// brinkLeft[0]: monk, brinkLeft[1]: devil
// brinkRight[0]: monk, brinkRight[1]: devil
bool check(int monkLeft, int devilLeft, int monkRight, int devilRight, char mode) {
if(monkLeft == 0 && devilLeft == 2 && monkRight == 2 && devilRight == 0
&& mode == 'Q')