osn_progr_final
.pdfint i,j,g=0,z=0; long cf;
static int a[10],b[10],c[10]; for(i=0,j=48;i<=9,j<=57;i++,j++)
{
a[i]=i;
b[i]=j;
}
for(j=0;j<=100;j++)
{
if(n==0)break;
cf=n%10;
n/=10;
for(i=0;i<10;i++)
{
if(a[i]==cf)
c[z++]=b[i];
}
}
for(z=9;z>=0;z--)
{
if(c[z]!=0)
str[g++]=c[z];
}
str[g]='\0';
}
void main()
{
static char str[80]; long n;
puts("Введіть ціле число n, яке треба перевести в ря-
док:\n"); scanf("%ld",&n); I_TO_B(n,str); puts("\nОсь рядок:\n"); puts(str);
getch();
}
Приклад 3
Написати програму для гри в "Хрестики-Нолики" на полі 3х3 для людини та комп”ютера.
#include<stdio.h>
#include<conio.h>
171
#define ESC 27
int win[24]={0,1,2,3,4,5,6,7, 8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6}; int prov1(int *a)
{
int i,p=0,w[3]; for(i=0;i<8;i++)
{
w[0]=win[i*3];
w[1]=win[i*3+1];
w[2]=win[i*3+2]; if(a[w[0]]==0&&a[w[1]]==0&&a[w[2]]==-1)
{
a[w[2]]=0;
p++;
break;
}
if(a[w[0]]==0&&a[w[1]]==-1&&a[w[2]]==0)
{
a[w[1]]=0;
p++;
break;
}
if(a[w[0]]==-1&&a[w[1]]==0&&a[w[2]]==0)
{
a[w[0]]=0;
p++;
break;
}
}
return p;
}
int prov2(int *a)
{
int i,p=0,w[3]; for(i=0;i<8;i++)
{
w[0]=win[i*3];
w[1]=win[i*3+1];
w[2]=win[i*3+2]; if(a[w[0]]==1&&a[w[1]]==1&&a[w[2]]==-1)
{
a[w[2]]=0;
p++;
break;
172
}
if(a[w[0]]==1&&a[w[1]]==-1&&a[w[2]]==1)
{
a[w[1]]=0;
p++;
break;
}
if(a[w[0]]==-1&&a[w[1]]==1&&a[w[2]]==1)
{
a[w[0]]=0;
p++;
break;
}
}
return p;
}
void main()
{
int i,j,p=0,l,a[9],n; do
{
clrscr(); for(i=0;i<9;i++)a[i]=-1; if(p==0)
{
puts("Комп’ютер ходить першим"); a[4]=0;
for(l=0;l<4;l++)
{
do
{
scanf("%d",&n); if(a[n]!=-1) puts("Клітинка зайнята!");
}while(a[n]!=-1); a[n]=1; if(prov1(a)!=0)
{puts("Ви програли!");break;} if(prov2(a)==0)
{
if(a[0]<0&&a[8]!=1)
a[0]=0;
else if(l==1&&a[1]==1) a[6]=0;
else if(a[2]<0&&a[6]!=1)
173
a[2]=0;
else for(i=0;i<9;i++) if(a[i]<0) {a[i]=0;break;}
}
for(i=0;i<3;i++,putchar('\n'))
for(j=0;j<3;j++) printf("%2d ",a[i*3+j]);
}
}
else
{
puts("Ви ходите першим"); scanf("%d",&n);
a[n]=1;
for(l=0;l<4;l++)
{
if(prov1(a)!=0)
{puts("Ви програли!");break;} if(prov2(a)==0)
{
if(a[4]==-1)a[4]=0;
else if(l==1&&a[0]==1&&a[8]==1||l==1&&a[2]==1&&a[6]==1) a[1]=0;
else if(a[0]<0&&a[8]!=1) a[0]=0;
else if(a[2]<0&&a[6]!=1) a[2]=0;
else for(i=0;i<9;i++) if(a[i]<0) {a[i]=0;break;}
}
for(i=0;i<3;i++,putchar('\n'))
for(j=0;j<3;j++) printf("%2d ",a[i*3+j]); do
{
scanf("%d",&n); if(a[n]!=-1) puts("Клітинка зайнята!");
}while(a[n]!=-1); a[n]=1;
}
}
for(i=0;i<3;i++,putchar('\n'))
174
for(j=0;j<3;j++) printf("%2d ",a[i*3+j]); p=!p;
puts("Знову?(Так-довільна клавиша, Ні-ESC)"); }while(getch()!=ESC);
}
Приклад 4
Із даної на площині множини точок вибрати такі чотири точки, котрі є вершинами випуклого чотирикутника найбільшої площі.
Для розв”язку задачі реалізуємо наступний підхід: будемо переглядати всі можливі четвірки точок , перевіряти, чи є вони вершинами випуклого чотирикутника і знаходити його площу при позитивній перевірці на випуклість. Тоді з усіх таких площ знайдемо максимальну. Для знаходження площі чотирикутника та перевірки його на випуклість будемо використовувати площі трикутників. Очевидно, що площа випуклого чотирикутника завжди дорівнюватиме сумі площ 2 трикутників, що утворюються його сторонами та довільною діагоналлю. Якщо ж чотирикутник не випуклий, то його площа дорівнює сумі площ трикутників лише при певному підборі вершин трикутників. Для знаходження площі трикутника використаємо наступну формулу. Нехай маємо точки з координатами (x1,y1), (x2,y2) та (x3,y3).
Тоді S=1/2| x1y2+ x2y3 +x3y1 -x1y3 –x2y1 –x3y2 |
#include <math.h> #include <stdio.h> #include <conio.h> #include <stdlib.h>
//Структура точки typedef struct
{
float x; float y; } tochka;
//Структура чотирикутника typedef struct
{
tochka t1; tochka t2; tochka t3; tochka t4;
} choturukyt;
175
//Обчислюємо площу трикутника за формулою, записаною вище
float s_tr(tochka t1,tochka t2,tochka t3)
{
return 0.5*fabs(t1.x*t2.y+t2.x*t3.y+t3.x*t1.y- t1.x*t3.y-t2.x*t1.y-t3.x*t2.y);
}
//Обчислюємо площу чотирикутника //Перевіряємо, чи є він випуклим
float s_ch(tochka t1,tochka t2,tochka t3,tochka t4)
{
float s1,s2;
s1=s_tr(t1,t2,t3)+s_tr(t1,t3,t4); s2=s_tr(t2,t3,t4)+s_tr(t1,t2,t4);
if(fabs(s1-s2)/s1<1e-4)return s1; return 0;
}
//Знаходимо найбільшу площу чотирикутника //Методом перебору всіх точок
float poshyk(tochka *A,int n,choturukyt *B)
{
long i,j,k,m; float pre=0,tek;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
for(k=j+1;k<n;k++)
for(m=k+1;m<n;m++)
if((tek=s_ch(A[i],A[j],A[k],A[m]))!=0) if(tek>pre)
{
pre=tek; B->t1=A[i]; B->t2=A[j]; B->t3=A[k]; B->t4=A[m];
}
return pre;
}
//Формуємо множину точок
void zapov(tochka *A,long n,long in)
176
{
long i; for(i=0;i<n;i++)
{
A[i].x=in*((float)rand()/(float)32767);
A[i].y=in*((float)rand()/(float)32767);
}
}
void main()
{
choturukyt B; tochka *A; float s; long n,in;
srand(time(NULL));
m1:
clrscr();
printf("Введіть кількість точок (N>4): "); scanf("%ld",&n);
printf("Введіть інтервал(IN>0) від 0 до "); scanf("%ld",&in);
if(n<4 || in<=0)
{
highvideo();
cputs("\nУвага! Помилка при вводі даних!"); normvideo();
getch(); goto m1;
}
if((A=(tochka*)malloc(n*sizeof(tochka)))==NULL)
{
highvideo();
cputs("\nПомилка при виділенні памяті!"); normvideo();
getch();
return;
}
zapov(A,n,in);
clrscr();
if((s=poshyk(A,n,&B))!=0)
{
puts("Точки чотирикутника:");
177
printf("Перша:\t\tx %9.3f\ty %9.3f\n",B.t1.x,B.t1.y); printf("Друга:\t\tx %9.3f\ty %9.3f\n",B.t2.x,B.t2.y); printf("Третя:\t\tx %9.3f\ty %9.3f\n",B.t3.x,B.t3.y); printf("Четверта:\tx %9.3f\ty %9.3f\n",B.t4.x,B.t4.y);
printf("\nПлоща цього чотирикутника: %.3f\n\n",s);
}
else puts("Таких чотирикутників немає!\n");
highvideo();
cputs("Для вихода натисніть Esc..."); putchar('\n');
cputs("Для повтора натисніть Enter..."); normvideo();
free(A);
m2:
switch(getch())
{
case 13: goto m1; case 27: return; default: goto m2;
}
}
Приклад 5. Множення n-вимірних матриць
Розглянемо спочатку, як можна собі уявити множення багатовимірних матриць і як визначити їх добуток. Звичайно, відоме множення звичайних прямокутних чи квадратних матриць за правилом “рядок на стовпчик”. Розглянемо “тривимірні” матриці А та B, елементи яких можуть бути записані, очевидно, у тривимірні масиви . Розглядаючи процес множення за аналогією з двовимірними матрицями, можемо уявити тривимірну матрицю А як вектор-стовпчик двовимірних:
|
|
A |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
A2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
A= |
|
|
|
|
B= (B , B ,..., B ) |
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
... |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
1 2 |
n |
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
An |
|
|
|
|
|
|
|
|
|
|
|
|
Аналогічно матрицю B можна уявити як вектор-рядок двовимірних матриць. Тоді результатом множення є конструкція:
178
C=|| сij || , i 1, n, j 1, n , де cij Ai * B j . Тут Ai * B j є звичайним множенням квадратних матриць і, отже, є двовивірною матрицею. З точки зору представлення даних результат множення тривимірних матриць є, очевидно, чотиривимірною матрицею і представляється чотиривимірним масивом. Тоді за рекурсією можемо визначити добуток довільних n-вимірних матриць A та B, розглядаючи їх відповідно як векторстовпчик та вектор-рядок n-1-вимірних матриць :
|
|
|
|
||
С=A*B, C=|| сij || , i |
1, n |
, j |
1, n |
, |
cij Ai * B j ( Ai , Bj –n-1-вимірні матриці). |
Тоді добутком n-вимірних матриць буде n+2-вимірна матриця (n>=4).
Відмітимо, що виходячи з способу розміщення в пам”яті n-вимірних масивів в С, будемо притримуватись такої ж домовленості, записуючи n-вимірні масиви у динамічному одновимірному. При цьому, будемо вважати, що для довільної n-вимірної матриці А, що представляється як вектор-стовпчик n-1-вимірних матриць A1 ,A2 ,…An,
|
|
A |
|
|
|
|
|
|
1 |
|
|
|
|
A= |
|
A2 |
|
в пам”яті послідовно записуються матриці A1 |
,A2 ,…An. |
|
|
... |
|
||||
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
An |
|
|
Відмітимо, що для реалізації відповідної рекурсивної функції нам зручно було б мати матрицю B, у якої б матриці B1 ,B2, …,Bn були розміщені в послідовних блоках пам”яті. Це можна досягти послідовно записуючи в одновимірний масив елементи вихідної матриці з кроком n. Тобто, спочатку записуємо 1-й елемент, потім n-й, 2n-й,3n- й,…, тоді 2-й, 2+n-й,2+2n-й,….Цю процедуру реалізуємо в функції ctranspon (int *a,int n,int m):
long pow(long n,int m) {int i; for(i=0;i<m-1;i++) n*=n;
return n;
}
/*часткове транспонування n-вимірної матриці*/ int* ctranspon (int *a,int n,int m)
179
{
int *rob1,*rob=(int*)malloc(sizeof(int)*pow(n,m)); rob1=rob;
long i,j; int *s;
for (j=0;j<n;j++)
{
s=a++;
for(i=0; i<pow(n,m-1); i++) *rob++=*(s+i*n);
}
return rob1;
}
При реалізації безпосередньо множення матриць будемо записувати результат множення окремих компонент у деякий масив. Причому на вхід функції буде передаватись блоки, що множаться , розмірності та адреса, куди записувати відповідні результати множення (у нашому випадку це **c). Після запису інформації при кожному виклику функції відповідна адреса повинна змінюватись (зсуватись на кількість елементів, що вже записані). Але в С при передачі адреси створюється її локальна копія в функції. Тобто, якщо передати в функцію просто адресу, то ми не зможемо з функції її змінити. Отже, необхідно передавати адресу цієї адреси (або використовувати механізм посилань, реаклізований в С++). Винакає також проблема корректного виділення пам”яті для результату множення. В нашому прикладі це робиться в функції main().
void dobutok(int* a, int* b, int** c, int n, int m)
/*змінна c буде містити результат множення. І, оскільки функція рекурсивно буде змінювати сам вказівник, то будемо передавати в функцію його адресу*/
{
180