PDA

View Full Version : hỏi đáp về bài tập C/C++



herolong
25-06-2007, 21:44
chào các bạn. mình mở topic này với mục đích có thể tập trung các bài tập về C/C++ về 1 nơi để người đọc có thể dễ tìm kiếm. đỡ phải đi tìm từng topic .
Mình có 1 bài tập về lập trình C. mong mọi người giúp mình

1. viết nguyên mẫu của các hàm( chỉ nguyên mẫu thôi)
-nhập/xuất mảng 1 chiều/2 chiều
-tính chu vi,diện tích,max,min
-tìm kiếm số,chuỗi
2.viết code hoàn chỉnh các yêu cầu sau( viết= hàm)
a,1 string: -nhập,xuất
- in ra string đảo ngược với string nhập vào
-đếm từ,xóa từ
-in mỗi từ trên 1 dòng
-tìm kiếm
b, với n string:
-nhập/xuất
-tìm và in ra xâu max/min
-tìm độ dài trung bình.
-tìm và in ra xâu có chứa xâu st
-ghép xâu
-sắp xếp
3, Mảng 1 chiều:
-nhập/xuất
-sắp xếp
-tính tổng toàn bộ/số dương/số chẵn,lẻ
-tìm số nguyên tố,số chính phương,max,min,trung bình
cảm ơn nhiều

linhtk
26-06-2007, 13:42
Hay nhỉ! Bác cũng tâm huyết đấy chứ.

khuongcong
26-06-2007, 13:49
Bác herolong đưa ra ý kiến hay đó, những hàm này rất hay dùng cho những người bắt đầu học C/C++ như em :)

mokona
26-06-2007, 14:51
Thật ra những bài này không khó chỉ cần biết sơ vài thuật toán là có thể làm được. Mình xin làm trước một vài bài nhưng theo kiểu C++ tức mình dùng cin, cout chứ không dùng printf hay scanf.
1. Nhập xuất mảng 1, 2 chiều:
//mang mot chieu
for (int i=0;i<n;++i) cin>>a[i];//mang mot chieu a[100], n tu nhap
//mang 2 chieu, ta xem như là ghi ma trận cấp m x n
for (int i=0;i<m;++i)
for (int j=0;j<n;++j)
cin>>a[i][j];
tinh chu vi, diện tích, max,min: quá chung chung không thể giải thích hết được. Mình chỉ làm phần max, min nhưng cho mảng thôi.
max=a[0][0];//gán cho thằng lớn nhất là phần tử đầu tiên
min=a[0][0];//tương tự
for (i=0;i<m;++i)
for (j=0;j<n;++j)
{
if (a[i][j]>max) max=a[i][j];//neu trong luc duyet mang ma thay thang nào lớn hơn thì gán thằng đó thành max
if (a[i][j]<min) min=a[i][j];//tương tự
}
//string,in chuỗi đảo ngược, đếm từ;
string a,b;
for (i=0;i<a.length();++i)
b[a.length()-i)=a[i];
cout<<b;
//nếu bạn dùng kiểu ký tự thì hàm lấy chiều dài chuỗi là strlen(char *)
//đếm từ
int dem;
for (i=0;i<a.length();++i)
if (a[i-1]!=char(32))&&(a[i]==char(32)||a[i]=='\0') dem++;
cout<<dem;
//việc xóa từ không cụ thể nhưng có hàm xóa từ như erase(char *,int a,int b), a.erase(int a,int b)
Có thể xem thông tin chi tiết của các hàm này trên trang web sau:
http://www.cplusplus.com.
//mang 1 chieu;
//sắp xếp;
for (i=0;i<n-1;++i)
for (j=n-1;j>i;--j)
if (a[i]>a[i]) HoanVi(a[i],a[j]);//ham HoanVi các bạn tự viết nhá;
//tong so duong, so chan le
int tong=0;
for (i=0;i<n;++i) if (a[i]%2==0) tong+=a[i];
//tuong tự cho mấy thằng lẻ và dương
//Số nguyên tố, số chính phương, số hoàn thiện
bool nguyento=true;
for (i=2;i<n;++i)//n la so do người dùng nhập
if (n%i==0) nguyento=false;
//dể làm số chính phương bạn cần tham khảo hàm làm tròn. Ở đây tôi tạm gọi hàm làm tròn xuống là round() vi tôi quên mất tên hàm rồi hình như là floor thì phải;
//n do người dùng nhập sẵn, các biến bool các bạn tự khai báo.
if (sqrt(n)-round(sqrt(n))==0) chinhphuong=true;
else chinhphuong=false;
//số hoàn thiện;
int tong;
for (i=1;i<n;++i)
if (n%i==0) tong+=i;
if (tong==n) shthien=true;
else shtien=false;

herolong
26-06-2007, 19:24
anh mokona nói rất chính xác. mấy bài này đều là những bài rất cơ bản.
có điều em nghĩ ta nên bắt đầu giải = ngôn ngữ C,vì đây là ngôn ngữ những người mới bắt đầu học lập trình hay học và tại vn thì aptech cũng dạy cho mình bắt đầu từ ngôn ngữ này.)

mokona
29-06-2007, 15:31
Ngon ngu C thi ban hay chuyen cac lenh nhap xuat cin,cout thanh printf,scanf (tham khao trong các sách) Vấn đề về chuỗi thì bạn hãy dùng kiểu mảng ký tự (char *) nhung minh khuyen hay dung cac bien kiểu string vì như vậy thì nó sẽ ít bị hư dữ liệu hơn.
VD: Bạn hãy tạo ra một mảng char nam[5]//dung de luu gia tri nam
sau do tao một mảng char nam1[5] khác và copy toàn bộ dữ liệu của mảng nam[5] sang bạn sẽ thấy như thế nào(dùng cách copy nào thì tùy bạn)

phan huy dao
07-07-2007, 14:34
cho trước mảng 1 chiều các số nguyên tố với kích thước MAX=100 phần tử
viết chương trình cho hiện menu công việc cho phép người dùng lựa chọn thực hiện như sau:
1. tạo trị ngẫu nhiên ban đầu cho các phần tử mảng trong đoạn [50...150]
2. xác định phần tử lẻ có giá trị nhỏ nhất
3. xác định phần tử chẵn có giá trị lớn nhât`
4. tính tổng tất cả các phần tử có chỉ số lẻ trong mảng
5.
tính tổng các phần tử có trong mảng có chỉ số chẵn đồng thời thỏa mãn điều kiện có trị là một số nguyên tố
bạn có thể giúp mình giải bài toán này
cám ơn!

evodanh
07-07-2007, 16:55
Các bài tập dạng Tin học đại cương hay kĩ thuật lập trình này các bạn nên tự làm lấy đi. Vì nó giúp cho bạn rèn luyện kĩ năng lập trình, tạo căn bản vững chắc cho các bạn sau này khi đi vào chuyên ngành.

mokona
09-07-2007, 06:10
1. Tao gia tri ngau nhien trong khoang [50-150]
dung hàm random: srand(time(NULL));r=rand()%101+50;
2. xác định phần tử lẻ có giá trị nhỏ nhất.
Đầu tiên xác định phần tử lẻ đầu tiên (dò qua mảng một lượt) sau đó gán nó bằng min. Rồi quét lại một lượt trong mảng xem coi phần tử nào lẻ thì so sánh với thằng min này tức (a[i]%2==1&&a[i]<min) min=a[i];
3. Tuơng tự
4. Đã làm ở phần trên
5. Chưa hiểu đề

vit_con
09-07-2007, 08:07
Các bài lập trình C cơ bản, mình thấy các bạn sẽ cảm thấy khó khăn nhất trong phần con trỏ và cấp phát bộ nhớ động.
Mình có 1 loạt slide giáo trình môn học system programming, học trên ngôn ngữ C. Liệu mình có nên dịch ra tiếng Việt hết và đưa lên đây không ?
Tuy nhiên các sample yêu cầu được biên dịch trên unix hoặc linux thì mới chạy đúng.

mokona
09-07-2007, 18:54
Phần con trỏ thì không khó nhưng mình nghĩ là cấp phát bộ nhớ mới đúng là một vấn đề quan tâm vì có rất nhiều kiểu cấp phát bộ nhớ và nhiều kiểu xử lý những hàm liên quan đến bộ nhớ như các hàm đồ họa (chỉ đối với TC và BC), còn việc sử dụng con trỏ thì bạn phải chú ý xem mục đích chính của con trỏ mà bạn đang sử dụng đó là dùng cho việc gì. VD: char *layten(char *hoten)//ở đây con trỏ layten được dùng để trỏ tới vủng lưu lại vị trí của một mảng ký tự do bạn trả về(Không biết mình nghĩ như vậy có đúng không).
Còn về giáo trình thì mình nghĩ là bạn nên post lên để chia sẻ cho mọi người vì nói chung thì giáo trình chỉ mang tính chất tham khảo thôi mình chắc cho dù ai có biết về nó rồi cũng sẽ đọc thôi để tự xem xem kiến thức hiểu biết của bản thân về mục này như thế nào

eXecutive
09-07-2007, 20:42
Hoan nghênh ý tưởng!!!
Tui xin đóng góp 1 xíu. Bắt đầu thì tương đối khó C khi mới nhập môn bởi vì còn lạ lẫm, đây là những cái rất cơ bản.

a. STRING

* Xử lý STRING là một công việc rất quan trọng vì nắm bắt được nó chúng ta có thể hiểu về mảng của C. Những công việc này có thể không cần phải làm nếu lập trình trên VC++ hay C#... không cần thiết nữa vì đã hỗ trợ trong các đối tượng chuyên dụng như CString hay System::String... nhưng khi nhập môn C bắt buộc phải biết!

- In ra string đảo ngược với string nhập vào



void eX_PrintInvertChar(char *lpString){
int nLen = strlen(lpString);
for (i = nLen-1;i>=0;i--){
printf("%c",lpString[i]);
}
}


- Đếm từ
Xử lý STR có thể ảnh hưởng tới chuỗi đưa vào nên nhớ copy ra một strTemp rồi sau đó muốn làm gì thì làm...



int eX_CountString(char* lpString){
char lpStrTemp[100];
char *lpStrTok;
int nCount=0;

strcpy(lpStrTemp,lpString);
// Tách từng từ... dựa vào ký tự khoảng trắng ' '
lpStrTok = strtok(lpString," ");
while (lpStrTok){
strcpy(aStr[i],lpStrTok );
i++;
lpStrTok = strtok(NULL," ");
}
return i;
}


- Xóa từ
. Xóa ký tự khoảng trắng ' ' ở đầu và cuối str.


void eX_DeleteInorgeChar(char* lpString,char *lpInorge){
int i,j,nLenStr;
int bDelete = 1;
// Xóa cuối câu
j = strlen(lpInorge);
while(bDelete){
nLenStr = strlen(lpString);
bDelete = 0;

for (i = 0;i<j;i++)
if (lpInorge[i] == lpString[nLenStr-1]){
bDelete = 1;
break;
}

lpString[nLenStr-1] = NULL;
}
// Xóa đầu câu
bDelete = 1;
while(bDelete){
bDelete = 0;
nLenStr = strlen(lpString);
for (i = 0;i<j;i++)
if (lpInorge[i] == lpString[0]){
bDelete = 1;
break;
}
nLenStr = strlen(lpString);
memmove((void*)&lpString[0],(void*)&lpString[1], nLenStr);
}
}


Ví dụ: "$#$abcd*(!@*" -> "abcd"

char *lpStr= "$#$abcd*(!@*";
eX_DeleteInorgeChar(lpStr,"$#(!@*");

. VD xóa từ ký tự i. Số ký tự xoá...


void eX_DeleteNChar(char* lpString,int nPos,int nLen){
memmove((void*)&lpString[nPos],
(void*)&lpString[nPos+nLen],
strlen(lpString) - nPos);
}


. Xóa từ thứ i trên chuỗi chỉ cần cải tiến một xíu mà thôi.

- In mỗi từ trên 1 dòng
Tương tự như đếm từ, nhưng printf("%s\n",lpStrTok) sau mỗi lần tácch.

- Tìm kiếm


void eX_FindPosString(char* lpString,char* lpFind){
char *lpTempString[100];
char *lpFind;

strcpy(lpTempString,lpString);
lpFind = strchr(lpTempString,lpFind);
while (lpFind!=NULL)
{
printf ("Tim thay o vi tri %d ",lpTempString-lpString+1);
pch = strchr(lpTempString + 1,lpFind);
}
}


- So sánh
Chủ yếu là dùng hàm
. strcmp "So sánh 2 str"
. stricmp "So sánh 2 str không phân biệt hoa hay thường"
. strncmp "So sánh n ký tự của 2 str"

Kết quả:
=0 -> 2 str giống nhau.
>0 -> Str1 > Str2
<0 -> Str1 < Str2

kcminh
18-07-2007, 11:10
Nhập mảng mà sử dụng hàm raondomize mà các giá trị trong mảng có giá trị âm thì làm sao

mokona
18-07-2007, 13:47
for (int i=0;i<n;++i) a[i]=rand()%k-k; //sẽ cho các giá trị từ -(k-1) đến 0
for (int i=0;i<n;++i) a[i]=rand()%(2*k)-k;//cho các giá trị từ -(k-1) đến k-1.

giaovien
19-07-2007, 10:10
có bác nào giúp em cái. em còn 5 bài khó nhất này em ko làm đc có bác nào thi giúp em với.

BÀi 1: cho một dãy số nguyên gồm n phần tử( 1<=n <=1000) câu hỏi:a. hãy nhập n và các phần tử của dãy số.
câu hỏi b . dãy con là tập hợp của mộtt số phần tử trong dãy ban đầu .không thay đổi thứ tự trước sau giữa chúng nhưng ko nhất thiết phải liên tiếp . hãy tìm dãy con tăng dài nhất.
ví dụ nếu có dãy số3,4,6,1,5,3,6,8,10,12,2,8,13 thì dãy con tăng dài nhất là 3,6,8,10,12.


bài 2: cho một ma trận số nguyên dương kích thước "m nhân n " (1<=m, n<=100). hãy tìm một dãy m ô thỏa mãn các điều kiện sau. -mỗi dòng lấy đúng một ô. --ô ở dòng i , cột J thì ô ở dòng i+1 chỉ có thể là cột j-1 ,,j hoặch j+1 và không vượt ra ngoài ma trận. --------tổng các số trong dãy ô tìm đựoc là lớn nhất

bài 3: Nhập vào một xâu ký tự ( giả thiết xâu nhập vào chỉ chứa các chữ cái , chữ số hoặch các dấu : dấu cách , dấu phẩy (,) .dấu chấm phẩy (., dấu chấm (.), dấu chấm than (!), dấu 2 chấm (. đếm xem trong xâu có bao nhiêu từ .Một từ là một dãy khác rỗng gồm liên tiếp các ký tự , không chứa dấu các dấu đã cho. ( hay nói cách khác là 2 từ cách nhau bởi ít nhất một trong các dấu đã cho)

bài 4: Cho thông tin của một loại sơn gồm.:tên sơn , tên sản xuất, số lượng , trọng lượng , năm hết hạn sử dụng. a) nhập thông tin của các loại sơn hộp theo yêu cầu.:quá trình nhập liên tục cho đến khi tên sơn ký tự "*". : đưa thông tin của tất cả các loại sơn ra màn hình theo dạng cột ( thông tin mỗi loại sơn trên một dòng), gồm : tên sơn, tên sản xuất, giá , số lượng, trọng lượng và thành tiền.(thành tiền = số lượng X đơn giá) . c): nhập vào một số nguyên X, xóa tất cả các loại sơn có năm sử dụng nhỏ hơn X. đưa danh sách các loại sơn còn lại ra màn hình .

bài 5 :lập một hàm, đầu vào là 3 số nguyên a,b,c, đầu ra là xâu ký tự "Đúng" hoặch "Sai" tươngg ứng với a,b,c là một ngày tháng năm nào đó hoặch không phải. ví dụ a=2, b=13, c=1234 thì hàm trả về giá trị "Sai", nếu a=2, b=3, c=1234 thì hàm trả về giá trị "Đúng". cho biết năm nhuận là năm chia hết cho 4, nhưng nếu C chia hết cho 100 thì cũng phải chia hết cho 400.

bài 6: Cho 1 lưới các ô vuông A kích thước m x n ( các ô của lưới chỉ chứa các giá trị 0 hoặc 1). Hai ô được gọi là cùng một miền liên thông nếu chúng có cùng giá trị và có thể "đi" được tới nhau thông qua các ô có cùng giá trị và sát cạnh. Hãy tìm số miền liên thông của A

eXecutive
21-07-2007, 13:15
Những bài toán này chẳng có ai rãnh mà đi giải dùm cho bạn đâu. Cái chính là bạn phải tự làm. Code dưới tui cài đặt từ 4rum luôn nên lỗi là chuyện dĩ nhiên, do đó bạn phải hiểu.



BÀI 1:
Cho một dãy số nguyên gồm n phần tử( 1<=n <=1000)
a. Hãy nhập n và các phần tử của dãy số.
b. Dãy con là tập hợp của một số phần tử trong dãy ban đầu. không thay đổi thứ tự trước sau giữa chúng nhưng ko nhất thiết phải liên tiếp . Hãy tìm dãy con tăng dài nhất.

Ví dụ nếu có dãy số 3,4,6,1,5,3,6,8,10,12,2,8,13 thì dãy con tăng dài nhất là 3,6,8,10,12.


Câu a thì dễ rồi.
Câu b.
- Bạn phải dùng một biến (int nPos) và một biến (int nLengh) để đánh dấu vị trí bắt đầu và độ dài của dãy con.



int nPos = 0, nPosl = 0;
int nLengh=0, nLenghl = 0;
int i;

while (nPos < n){ // n số phần tử của dãy
nLengh = 0;
for (i = 0;i<n-nPos;i++){
if (aMang[nPos + i] > aMang[nPos + i-1]){
// Dãy con vẫn tăng
nLengh++;
}
else{
// Kết thúc dãy con tăng
if (nLengh > nLenghl){
nLenghl = nLengh;
nPosl = nPos;
}
// Đặt vị trí pos mới
nPos += i;
break;
}
}
}

// In dãy con dài nhất
for (i = 0;i<nLenghl;i++)
cout << aMang[nPosl + i] << " ";




BÀI 2:

Cho một ma trận số nguyên dương kích thước "m x n " (1<=m, n<=100).

Hãy tìm một dãy m ô thỏa mãn các điều kiện sau.
- Mỗi dòng lấy đúng một ô.
+ Ô ở dòng i , cột j thì ô ở dòng i+1 chỉ có thể là cột j-1 , j hoặc j+1 và không vượt ra ngoài ma trận.

- Tổng các số trong dãy ô tìm được là lớn nhất


Sorry nha! tui ko hiểu đề!



BÀI 3:
Nhập vào một xâu ký tự ( giả thiết xâu nhập vào chỉ chứa các chữ cái , chữ số hoặc các dấu : dấu cách , dấu phẩy (,) .dấu chấm phẩy (., dấu chấm (.), dấu chấm than (!), dấu 2 chấm (. đếm xem trong xâu có bao nhiêu từ.

Một từ là một dãy khác rỗng gồm liên tiếp các ký tự, không chứa dấu các dấu đã cho. ( hay nói cách khác là 2 từ cách nhau bởi ít nhất một trong các dấu đã cho)


Bài này quá dễ, một từ được ngăn cách bởi các dấu đặc biệt, như vậy chỉ cần đếm các dấu này trong chuỗi thì có thể suy ra được string đó có bao nhiêu từ.



int nCount = 0;
for (i = 0;i<strlen(lpStr);i++_{
if (lpStr[i] == ' ' || lpStr[i] == ':' || lpStr[i] == ',' ... )
&& (lpStr[i-1] != ' ' || lpStr[i-1] != ':' ... )
nCount ++;

// Nếu ký tự hiện hành đang xét là các dấu đặc biệt
// và ký tự trước đó phải là chữ thì đó là một từ
}
cout << lpStr << "co tat ca " << nCount << "tu"




BÀI 4
Cho thông tin của một loại sơn gồm:
+ Tên sơn,
+ tên sản xuất
+ Số lượng
+ Trọng lượng
+ Năm hết hạn sử dụng.

a) Nhập thông tin của các loại sơn hộp theo yêu cầu:

- Quá trình nhập liên tục cho đến khi tên sơn ký tự "*"
- Đưa thông tin của tất cả các loại sơn ra màn hình theo dạng cột ( thông tin mỗi loại sơn trên một dòng). Gồm : tên sơn, tên sản xuất, giá , số lượng, trọng lượng và thành tiền.(thành tiền = số lượng X đơn giá) . c):

- Nhập vào một số nguyên X, xóa tất cả các loại sơn có năm sử dụng nhỏ hơn X. đưa danh sách các loại sơn còn lại ra màn hình .


Có 2 cách viết code để giải quyết bài này.
- Nếu là tôi thì tôi sẽ chọn HƯỚNG ĐỐI TƯỢNG (OBJECT)
- Nhưng có lẽ bạn chỉ mới học C nên tôi sẽ giải theo TRỪU TƯỢNG DỮ LIỆU (STRUCT)



typedef struct TAGThongtin_Son{
char lpTenSon[100];
char lpNSX[100];
int nSoluong;
int nTrongluong;
int nNamhethan;
}TTSON;

void Nhap(TTSON aMang[],int *n){
char lpTemp[100]
int nTemp;
int i = 0;

printf("Nhap thong tin son. Nhap ten son = '*' de ket thuc.\n");

while(1){
printf("Ten son: "); gets(lpTemp);
if (lpTemp[0] == '*')
break;
strcpy(aMang[i].lpTenSon,lpTemp);

printf("Ten NSX: "); gets(lpTemp);
strcpy(aMang[i].lpNSX,lpTemp);

printf("So luong: "); scanf("%d",&nTemp);
aMang[i].nSoluong = nTemp;

printf("Trong luong: "); scanf("%d",&nTemp);
aMang[i].nTrongluong = nTemp;

printf("Nam het han: "); scanf("%d",&nTemp);
aMang[i].nNamhethan = nTemp;
i++;
if (i == 100) break;
}
*n = i;
}

void Xuat(TTSON aMang[], int n){
int i = 0;
for (i = 0;i<n;i++){
printf("%s - %s - %d - %d - %d \n",
aMang[i].lpTenSon,
aMang[i].lpNSX,
aMang[i].nSoluong,
aMang[i].nTrongluong,
aMang[i].nNamhethan;
}
}

void Xoa(TTSON aMang[], int* n, int X){
int i;

for (i = 0;i<*n;i++)
if (aMang[i].nNamhethan < X){
memmove(aMang[i],aMang[i+1],sizeof(TTSON)*(n-1-i) );
*n--;
}
}




BÀI 5:
Lập một hàm, đầu vào là 3 số nguyên a,b,c, đầu ra là xâu ký tự "Đúng" hoặch "Sai" Tương ứng với a,b,c là một ngày tháng năm nào đó hoặc không phải.

Ví dụ a=2, b=13, c=1234 thì hàm trả về giá trị "Sai", nếu a=2, b=3, c=1234 thì hàm trả về giá trị "Đúng".

Cho biết năm nhuận là năm chia hết cho 4, nhưng nếu C chia hết cho 100 thì cũng phải chia hết cho 400.


Bài này có gì đâu mà phải suy nghĩ. Chỉ là vài phép so sánh if thôi!



BÀI 6:
Cho 1 lưới các ô vuông A kích thước m x n ( các ô của lưới chỉ chứa các giá trị 0 hoặc 1). Hai ô được gọi là cùng một miền liên thông nếu chúng có cùng giá trị và có thể "đi" được tới nhau thông qua các ô có cùng giá trị và sát cạnh. Hãy tìm số miền liên thông của A


Bài này dựa trên PP "vết dầu loang". "vết dầu loang" dùng để tìm đường đi, còn ở đây chỉ sử dụng cách tìm tường của nó để dánh dầu các miền liên thông, dĩ nhiên chắc chắn phải dùng đệ quy mới làm được bài này.



#define M 100
#define N 100

void dauloang(int aMang[][N],
int aTemp[][N],
int i, int j,
int nSet){

aTemp [i][j] = nSet; // Đánh dấu miền liên thông.

// Loang lần lượt qua phải, trái, trên, dưới

if ( aMang[i][j+1] == aMang[i][j]
&& aTemp[i][j+1] == 0 )
dauloang ( aMang,aTemp, i , j+1 ,nSet);

if ( aMang[i][j+1] == aMang[i][j]
&& aTemp[i][j+1] == 0 )
dauloang ( aMang,aTemp, i , j-1 ,nSet);

if ( aMang[i + 1][j] == aMang[i][j]
&& aTemp[i][j+1] == 0 )
dauloang ( aMang,aTemp, i + 1, j ,nSet);

if ( aMang[i - 1][j] == aMang[i][j]
&& aTemp[i][j+1] == 0 )
dauloang ( aMang,aTemp, i - 1, j ,nSet);

}

int TimSoMienLienThong(int aMang[][N){
int aTemp[M][N];
int i,i;
int nLienThong=1;
memset(aTemp,0,sizeof(int)*M*N); // Gán toàn bộ gt 0 cho MT

for (i = 0;i<M;i++){
for (j = 0;j<N;j++){
// Nếu chưa đánh dấu

if (aTemp[i][j] != 0){
dauloang (aMang,aTemp,i,j,nLienThong);
nLienThong ++;
}
}
}
return nLienThong; // Trả về số miền liên thông.
}


Đoạn code trên sử dụng đệ quy và tôi ko làm trên IDE nên khả năng lỗi DUMP rất cao. Vấn đề là bạn phải hiểu và biết cách DEBUG mới thành công được. Ý tưởng của thuật toán này như sau.

Giả sử ma trận khi nhập vào ban đầu '_' tượng trưng cho giá trị 0.



1 1 1 _ _ _ _ _ _
_ 1 1 _ 1 1 1 _ _
_ _ 1 _ 1 1 1 _ _
_ _ 1 _ 1 1 1 _ _
_ _ _ _ _ _ _ _ _
_ _ _ 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1


Khi gọi hàm dầu loang, nó sẽ đánh dấu ma trận aTemp như sau:
Cứ mỗi lần gọi dauloang(..) thì nó sẽ đánh dấu một miền liên thông với giá trị nSet.



Gọi lần 1:
1 1 1 _ _ _ _ _ _
_ 1 1 _ _ _ _ _ _
_ _ 1 _ _ _ _ _ _
_ _ 1 _ _ _ _ _ _
_ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _

Gọi lần 2:

1 1 1 2 2 2 2 2 2
2 1 1 2 _ _ _ 2 2
2 2 1 2 _ _ _ 2 2
2 2 1 2 _ _ _ 2 2
2 2 2 2 2 2 2 2 2
2 2 2 _ _ _ _ _ _
_ _ _ _ _ _ _ _ _

và sau 4 lần :

1 1 1 2 2 2 2 2 2
2 1 1 2 3 3 3 2 2
2 2 1 2 3 3 3 2 2
2 2 1 2 3 3 3 2 2
2 2 2 2 2 2 2 2 2
2 2 2 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4


Sau khi đã đánh dấu hết các miền thì chúng ta có thể suy ra được số miền liên thông. Ở ví dụ trên là 4.

mokona
21-07-2007, 15:07
Bài 3 của bác sẽ bị lỗi nếu người dùng ko nhập 1 khoảng trắng mà nhập từ 2 khoảng trắng trở lên. Mình cũng đã từng bị tình trạng trên nên đả rút ra kinh nghiệm khác rồi.

eXecutive
21-07-2007, 15:35
Sao mà lỗi nhỉ? Trước khi tăng số lượng từ tui đã kiểm tra ký tự phía trước nó rồi mà...
Dĩ nhiên thực tế thì cái này cũng die bởi i = 0 thì lại xảy ra lỗi, do đó phải chạy từ i = 1 hehe thông cảm, lập trình từ 4rum mà..


if (lpStr[i] == ' ' || lpStr[i] == ':' || lpStr[i] == ',' ... )
&& (lpStr[i-1] != ' ' || lpStr[i-1] != ':' ... )

mokona
21-07-2007, 18:20
Minh thi lam theo cach xoa tat ca nhung cai ky tu do di (";","!",v.v...) thi luc do se con lai dong chu binh thuong. Va ta se dem tu binh thuong bằng cách:
for (int i=0;i<strlen(str);++i)
if ((str[i-1]!=char(32))&& (str[i]==char(32)||str[i]=='\0') tu++;
Chỉ vậy thôi

thutuongtk
27-04-2009, 13:39
cac ban oi cho minh hoi doan code cua bai tap tinh dien tich hinh vuong lam sao cac ban

Mickey33884
26-04-2010, 07:57
Híc, thầy giáo cho bài tập làm đồ án 30% về bài tập Toán rời rạc, bài tập khó wá, lại mới học 1 buổi nên em hok làm được. Cả hướng làm cũng chưa có luôn. híc. Mọi người xem và giúp em với nhé.
Đề bài: Trình bày nguyên lí Direct
Giải các bài sau:
1)- Cho n là số nguyên dương bất kì, chứng minh rằng luôn lấy ra được từ n số đã cho 1 số số hạng thích hợp sao cho tổng của chúng chia hết cho n.
2)- Trong một cuộc lấy ý kiến vè 7 vấn đề, người được hỏi ghi vào một phiếu trả lời sẵn bằng cách để nguyên hoặc phủ định các câu trả lời tương ứng với 7 vấn đề đã nêu.
3)- Chứng minh rằng với 1153 người được hỏi luôn tìm được 10 người trả lời giống hệt nhau.
4)- Có 17 nhà bác học viết thư cho nhau trao đổi 3 vấn đề, chứng minh rằng luôn tìm được 3 người cùng trao đổi 1 vấn đề.
5)- Trogn kì thi kết thúc học phần toán rời rạc có 10 câu hỏi. Có bao nhiêu cách gán điểm cho các câu hỏi nếu tổng số điểm bằng 100 và mỗi câu ít nhất được 5 điểm.
6- Phương trình x1+x2+x3+xx4+x5=21 có bao nhiêu nghiệm nguyên không âm?
Yêu cầu bài: giải chi tiết, có ghi rõ các chú thích.
Híc.. mọi người cố gắng cho em hướng giải quyết nhé.
Em xin chân thành cám ơn!
Pm cho em theo địa chỉ skype : mickey33884 nha.