CÁC BÀI TOÁN TRÊN MA TRẬN
(Gồm có: Tạo ra ma trận xoắn ốc, Sudoku, Caro, Dò mìn ,Stack ,Queue ,Các thao tác cơ bản)
1. Tạo ra ma trận xoắn ốc :
void xoanoc(int a[][MAX], int n)
{
int k=1; //giá trị dùng để điền vào ma trận
int left=0, //các biên trái phải trên dưới
right=n-1, //dùng để làm chốt chặn
top=0,
bottom=n-1;
int i=0,j=-1; //tăng j trước rồi mới điền giá trị
while (k<=n*n){ //chưa điền đủ n*n số thì còn lặp
//B1: chạy dọc biên trên từ trái sang phải
while (j<right) a[i][++j] = k++;
top++; //điều chỉnh lại biên trên
//B2: chạy dọc biên phải từ trên xuống dưới
while (i<bottom) a[++i][j] = k++;
right ; //điều chỉnh lại biên phải
//B3: chạy dọc biên dưới từ phải sang trái
while (j>left) a[i][ j] = k++;
bottom ;
//B4: chạy dọc biên trái từ dưới lên trên
while (i>top) a[ i][j] = k++;
left++;
}
}
2. Caro :
void main()
{
int a[MAX][MAX],n;
docData(a,n);
inMat(a,n);
if(!kiemTraHopLe(a,n))
cout<<"Du lieu vao khong hop le !!!"<<endl;
else
{
cout<<"Du lieu vao hop le !!!"<<endl;
int kt=KiemTraThangThua(a,n);
if(kt!=-2)
cout<<kt<<" thang !!!"<<endl;
else
cout<<"Dang choi !!!"<<endl;
}
}
void docData(int a[MAX][MAX],int &n)
{
FILE *fin;
fopen_s(&fin,"INPUT.TXT","rt");
if(!fin)
{
cout<<"No file !!!"<<endl;
return;
}
// nhap n
fscanf_s(fin,"%d",&n);
// nhapma tran
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
fscanf_s(fin,"%d",&a[i][j]);
fclose(fin);
}
// in ma tran
void inMat(int a[MAX][MAX],int n)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
//cout<<a[i][j]<<"\t";
printf("%2d ",a[i][j]);
cout<<endl;
}
}
// kiem tra hop le
int kiemTraHopLe(int a[MAX][MAX],int n)
{
int demA=0,demB=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(a[i][j]==0 || a[i][j]==-1 || a[i][j]== 1)
{
if(a[i][j]==0)//dem cho ben A
demA++;
if(a[i][j]==1)// dem cho ben B
demB++;
}
else
{
return 0;
}
}
if(demA==demB || demA-demB==1 || demB-demA==1)
return 1;
return 0;
}
//
//kiem tra thang thua
int KiemTraThangThua(int a[MAX][MAX],int n)
{
if(n<5)
return -2;
else
{
//cac bien chung
int hs,// he so cong cua cac hang va cot
dem=0,// so lan bang nhau cua cac nuoc
i,j;// cac he so chay
//hang ngang
for(i=0;i<n;i++)//cac hang dang xet
{
for(hs=0;hs<=n-5;hs++)
{
for(j=hs;j<hs+4;j++)// xet 5 o hang ngang
{ // tu hs den hs+5
if(a[i][j]!=-1 && a[i][j+1]!=-1)
if(a[i][j]==a[i][j+1])
dem++;
else//ko bang nhau
j=hs+5;
else// co phan tu trong
j=hs+5;
}
if(dem==4)
{
cout<<"Thang hang ngang !!!"<<endl;
return a[i][hs];
}
dem=0;
}
}
//hang doc
dem=0;
for(j=0;j<n;j++)
{
for(hs=0;hs<=n-5;hs++)
{
for(i=hs;i<hs+4;i++)
{
if(a[i][j]!=-1 && a[i+1][j]!=-1)
if(a[i][j]==a[i+1][j])
dem++;
else//ko bang nhau
i=hs+5;
else//co phan tu trong
i=hs+5;
}
if(dem==4)
{
cout<<"Thang hang doc !!!"<<endl;
return a[hs][j];
}
dem=0;
}
}
//hang cheo
dem=0;
int demp=0;
for(i=0;i<=n-5;i++)// xet hang tu 0 den =n-5
for(j=0;j<=n-5;j++)//xet cot tu 0 den =n-5
{
for(int k=0;k<=3;k++)// he so cong 0 1 2 3
{
if(a[i+k][j+k]!=-1 && a[i+k+1][j+k+1]!=-1)
{
if(a[i+k][j+k]==a[i+k+1][j+k+1])//phan tu lien
tiep tren
dem++;
//hang cheo bang nhau
}
if( a[i+k][j+4-k]!=-1 && a[i+k+1][j+4-k-1]!=-1)
{
if( a[i+k][j+4-k]==a[i+k+1][j+4-k-1])
demp++;//phan tu tren hang cheo nguoc
}
}
if(dem==4)
{
cout<<"Thang hang cheo !!!"<<endl;
return a[i][j];
}
dem=0;
if(demp==4)
{
cout<<"Thang hang cheo !!!"<<endl;
return a[i][j+4];
}
demp=0;
}
}
return -2;
}
3. Dò mìn :
//ham random
int random(int n)
{
int a=rand();
return a%n;
}
//
//ham dat min vao ma tran
void datMin(int a[MAX][MAX],int n,int somin)
{
int i,j;
//khoi tao toan mang bang 0
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a[i][j]=0;
// dat tung qua vao ma tran
while(somin>0)
{
i=random(n);
j=random(n);
if(a[i][j]==0)// chua co min
{
a[i][j]=-1;// dat min vao
somin ; // cap nhat lai so min con lai
}
}
}
// tinh toan gia tri so min dat xung quanh
void tinhSoMin(int a[MAX][MAX],int n )
{
int i,j,k,l,dem;
//
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(a[i][j]!=-1)
{
dem=0;
for( k=i-1;k<=i+1;k++)
for( l=j-1;l<=j+1;l++)
if( k>=0 && k<n &&
l>=0 && l<n &&
(k!=i || l!=j) &&
a[k][l]==-1
)
{
dem++;
}
a[i][j]=dem;
}
}
// 6.viet ham tim vi tri ma xung quanh co nhieu min nhat
void ViTriNhieuMin(int a[MAX][MAX],int n)
{
int vti=0,vtj=0,
soMin,CoKhoiTao=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(a[i][j]!=-1)
{
if(CoKhoiTao==0)
{
soMin=a[i][j];
vti=i;
vtj=j;
CoKhoiTao=1;
}
else
{
if(a[i][j]>soMin)
{
soMin=a[i][j];
vti=i;
vtj=j;
}
}
}
}
printf("Vi tri nhieu min nhat la :[%d][%d]\n",vti,vtj);
}
//
// 7.tim vung co kich thuoc k*k (0<k<n)co it min nhat
//k cho truoc
void VungItMin(int a[MAX][MAX],int n,int k)
{
int CoKhoiTao=0,//co khoi tao
min=-1,//cho it min
vtmini=-1,vtminj=-1;//vi tri vung KxK
for(int i=0;i<n-k;i++)
for(int j=0;j<n-k;j++)
{
int tam=DemMin(a,n,i,j,k);
if(CoKhoiTao==0)
{
min=tam;
vtmini=i;
vtminj=j;
CoKhoiTao = 1;
}
else
{
if(tam<min)
{
min=tam;
vtmini=i;
vtminj=j;
}
}
}
cout<<"Vi tri vung k*k it min:["<<vtmini<<"]["<<vtminj<<"]"<<endl;
cout << "So min it nhat do la :" << min << endl;
}
//
//dem min trong pham vi KxK
int DemMin(int a[MAX][MAX],int n,int k,int vti,int vtj)
{
int dem=0;
for(int i=vti;i<vti+k;i++)
for(int j=vtj;j<vtj+k;j++)
{
if(a[i][j]==-1)
dem++;
}
return dem;
}
//
// 8.Ham cho biet vung lon nhat chua cac so 0 lien ke // co bao nhieu o
void DemO(int a[MAX][MAX],int n)
{
int Max=-1,//so o trong it nhat cua vung dang xet
CoMin=0,// co danh dau khoi tao Min
Vungi=-1,Vungj=-1;//vi tri vung it min nhat
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(a[i][j]==0)
{
int tami=i,tamj=j;//luu lai vi tri hien tai
a[i][j]=-9;
int dem=1,
kiemtra;
//luu vao stack
ST[top].i=i;
ST[top++].j=j;
//
DuyetO(a,n,i,j,kiemtra);
int isave=i,jsave=j;
//
while(top>0)//chua het stack
{
if(kiemtra==0)//het o duyet
{
i=ST[top-1].i;
j=ST[top-1].j;
top ;
}
else//con o chua duyet
{
a[i][j]=-9;
ST[top].i=isave;
ST[top].j=jsave;
top++;
dem++;
}
//printfMat(a,n);
//int chay;
//cin>>chay;
isave=i;//luu vi tri i dang duyet
jsave=j;//luu vi tri j dang duyet
DuyetO(a,n,i,j,kiemtra);
}
//khoi phuc lai i,j
i=tami;
j=tamj;
if(CoMin==0)// chua khoi tao max
{
Max=dem;
Vungi=i;
Vungj=j;
CoMin=1;
}
else
{
if(dem>Max)
{
Max=dem;
Vungi=i;
Vungj=j;
}
}
}
}
if(Max!=-1)
{
cout<<"Vung co nhieu o so 0 nhat la vung:[";
cout<<Vungi<<"]["<<Vungj<<"]"<<endl;
cout<<"So o vung do la:"<<Max<<endl;
}else
cout<<"khong co vung co o so 0 !!!"<<endl;
}
//
//ham kiem tra xem xung quanh con o nao duyet dc nua hay ko
//duyet tiep dc ->1
//ko duyet teip dc->0
void DuyetO(int a[MAX][MAX],int n,int &vti,int &vtj,int &kiemtra)
{
for(int i=vti-1;i<=vti+1; i++)
for(int j=vtj-1;j<=vtj+1;j++)
{
if(i>=0 && j>=0)
{
if(a[i][j]==0)
{
vti=i;
vtj=j;
//cout<<"Trong ij="<<vti<<" "<<vtj<<endl;
kiemtra=1;//con o de duyet tiep
return;
}
}
}
kiemtra=0;// het o de duyet
//khi ket thuc tra ra vi tri dau tien
//ma co the duyet den vao vti va vtj
}
4. Stack :
//Khai báo cấu trúc dữ liệu ngăn xếp (STACK)
//sử dụng mảng 1 chiều để lưu trữ nội dung
#define MAX 100
typedef struct {
int top;
int arr[MAX];
}STACK;
//Các thao tác trên ngăn xếp
//1. Khởi tạo 1 ngăn xếp rỗng
void init(STACK &s){
s.top = -1;
}
//2. Kiểm tra xem ngăn xếp có rỗng hay không
int isempty(STACK s){
return (s.top==-1);
}
//3. Kiểm tra xem ngăn xếp đã đầy hay chưa
int isfull(STACK s){
return (s.top==MAX-1);
}
//4. Cất 1 giá trị x vào ngăn xếp
void push(STACK &s, int value){
if (!isfull(s)){
s.top++;
s.arr[s.top] = value;
}
}
//5. Lấy 1 giá trị ra khỏi đỉnh ngăn xếp
int pop(STACK &s){
if (isempty(s)) return 0; //giá trị đặc biệt
int t = s.arr[s.top];
s.top ;
return t;
}
5. Các thao tác cơ bản :
//1. Tìm dòng có tổng lớn nhất của ma trận
//Trả về số thứ tự của dòng có tổng đạt max
//Tham số t chứa giá trị tổng của dòng đạt max
int maxdong(int a[][MAX], int d, int c, int &t)
{
int i,j,td=0,vt;
for(j=0; j<c; j++) td += a[0][j]; //tính tổng dòng 0
t = td; vt = 0; //giả sử dòng đầu đạt max
for(i=1; i<d; i++){ //duyệt từ dòng thứ 1 trở đi
td = 0; //tính lại từ đầu khi sang dòng mới
for(j=0; j<c; j++) td += a[i][j]; //tính tổng dòng i
if (t<td) { //dòng i có tổng lớn hơn
t = td; //cập nhật lại max
vt = i; //và chỉ số dòng
}
}
return vt;
}
//2. Cộng 2 ma trận (cùng kích thước dxc)
void congmt(int a[][MAX], int b[][MAX], int t[][MAX], int d, int c)
{
int i,j;
for(i=0; i<d; i++)
for(j=0; j<c; j++)
t[i][j] = a[i][j] + b[i][j];
}
//3. Nhân 2 ma trận (mxn) và (nxp)
//Ma trận tích có kích thước mxp
void nhanmt(int a[][MAX],int b[][MAX],int t[][MAX],int m, int n, int p)
{
int i,j,k;
for(i=0; i<m; i++) //duyệt qua ma trận T
for(j=0; j<p; j++){
t[i][j]=0; //khởi gán ban đầu
for(k=0; k<n; k++) //cộng dồn các tích
t[i][j] += a[i][k]*b[k][j];
}
}
//Một số thao tác trên ma trận vuông cấp nxn
//4. Kiểm tra ma trận đơn vị
int mtdonvi(int a[][MAX], int n)
{
int i,j;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
if ((i==j && a[i][j]!=1)||(i!=j && a[i][j]!=0))
return 0;
return 1;
}
//5. Kiểm tra ma trận tam giác dưới
int mttamgiacduoi(int a[][MAX], int n)
{
int i,j;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
if ((i>=j && a[i][j]==0)||(i<j && a[i][j]!=0))
return 0;
return 1;
}
//6. Kiểm tra ma trận tam giác trên
int mttamgiactren(int a[][MAX], int n)
{
int i,j;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
if ((i<=j && a[i][j]==0)||(i>j && a[i][j]!=0))
return 0;
return 1;
}
//7. Kiểm tra ma trận đối xứng
int mtdoixung(int a[][MAX], int n)
{
int i,j;
for(i=0; i<n; i++)
for(j=i+1; j<n; j++)
if (a[i][j]!=a[j][i])
return 0;
return 1;
}
//8. Tạo ma trận chuyển vị
void mtchuyenvi(int a[][MAX], int at[][MAX], int n)
{
int i,j;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
at[j][i] = a[i][j];
}
6. Hình vuông Latin:
//kiem tra cot
int ktcot(int a[MAX][MAX], int k,int n)
{
for(int i=0; i<n; i++)
for(int j=i+1; j<n; j++)
{
if (a[i][k] && a[i][k]==a[j][k])
return 1;
if(a[i][j]>n || a[i][j]<1 )
return 1;
}
return 0;
}
//Kiểm tra dòng k có vi phạm hay không
int ktdong(int a[][MAX], int k,int n)
{
for(int i=0; i<n; i++)
for(int j=i+1; j<n; j++)
{
if (a[k][i] && a[k][i]==a[k][j])
return 1;
if(a[i][j]>n || a[i][j]<1 )
return 1;
}
return 0;
}
//kiểm tra vị trí i,j có vi phạm hay không
int VitriViPham(int a[MAX][MAX],int n,int i,int j)
{
int k;
k=ktdong(a,i,n);
if(k==1)
return 1;
k=ktcot(a,j,n);
if(k==1)
return 1;
return 0;
}