经典矩形问题
生成各种矩阵是竞赛时经常考的一种题目,如何用C语言或C++生成以下形式几种矩阵:
第一种矩阵:
1 2 9 10
4 3 8 11
5 6 7 12
16 15 14 13
第二种矩阵蛇形)
1 2 6 7
3 5 8 13
4 9 12 14
10 11 15 16
第三种矩阵:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
第四种矩阵:
7 6 5 16
8 1 4 15
9 2 3 14
10 11 12 13
规律提示:
1.1->2 9->10
4<-3 8 11
5->6->7 12
16<-15<-14<-13
2.每个左上三角的数都是连续的
3.一个回旋阵,从外到里是连续的。
4.同样是回旋,从里到外是连续的。
第一种矩阵算法:
#include<iostream.h>
#include<iomanip.h>
void main()
{
const int N=20;
int i=0,j=0,a[N][N];
int lap=1,m=1,n;
while(1)
{
cout<<"/ninput matrix row N(N>=2): ";
cin>>n;
cout<<endl;
if(n>=2) break;
}
a[j]=m++;
lap++;
while(lap<=n)
{
if(lap%2==0)
{
for(j++;i<lap;i++)
a[j]=m++;i--;
for(j--;j>=0;j--)
a[j]=m++;j++;
}
else
{
for(i++;j<lap;j++)
a[j]=m++;j--;
for(i--;i>=0;i--)
a[j]=m++;i++;
}
lap++;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<setw(4)<<setiosflags(ios::left)<<a[j];
cout<<endl;
}
cout<<endl;
}
第二种矩阵算法:(蛇形)
#include<iostream.h>
#include<iomanip.h>
void main()
{
const int MAXLEN=10;
int nLen;
int nSnake[MAXLEN][MAXLEN];
do
{
cout<<"/ninput an integer less then "<<MAXLEN<<": ";
cin>>nLen;
cout<<endl;
}while(nLen>MAXLEN);
int i=0,j=0,s=1,nNum=1;
//s标记升降方向,斜向上为升(s==1),斜向下为降(s==-1)
while(1)
{
if(s==1)
{
nSnake[j]=nNum;
if(i-1<0)
{
if(j+1==nLen)
i++;
else
j++;
s=-1;
}
else
if(j+1==nLen)
{
i++;
s=-1;
}
else
{
i--;
j++;
}
}
else
{
nSnake[j]=nNum;
if(j-1<0)
{
if(i+1==nLen)
j++;
else
i++;
s=1;
}
else
if(i+1==nLen)
{
j++;
s=1;
}
else
{
i++;
j--;
}
}
nNum++;
if(nNum>nLen*nLen)
break;
}
for(i=0;i<nLen;i++)
{
for(j=0;j<nLen;j++)
cout<<setw(4)<<setiosflags(ios::left)<<nSnake[j];
cout<<endl;
}
cout<<endl;
}
第三种矩阵算法:
#include<iostream.h>
#include<iomanip.h>
void main()
{
const int N=20;
int i=0,j=0,a[N][N],n;
int m=1,x1,x2,y1,y2,s=1;
//x1,x2,y1,y2为上、下、左、右边界
//s标记数组元素升降,s==1为升,s==-1为降
while(1)
{
cout<<"/ninput matrix row N(N>=2): ";
cin>>n;
cout<<endl;
if(n>=2)
break;
}
x1=0;y1=0;x2=n;y2=n;
while(1)
{
if(s==1)
{
for(j;j<y2;j++)
a[j]=m++;
j--;i++;y2--;
for(i;i<x2;i++)
a[j]=m++;
i--;j--;x2--;
s=-1;
}
else
{
for(j;j>=y1;j--)
a[j]=m++;
j++;i--;y1++;
for(i;i>=x1+1;i--)
a[j]=m++;
i++;j++;x1++;
s=1;
}
if(m>n*n)
break;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<setw(4)<<setiosflags(ios::left)<<a[j];
cout<<endl;
}
cout<<endl;
}
第四种矩阵算法:
#include<iostream.h>
#include<iomanip.h>
void main()
{
const int N=20;
int i=0,j=0,a[N][N],n;
int m,x1,x2,y1,y2,s;
//x1,x2,y1,y2为上、下、左、右边界
//s标记数组元素升降,s==1为升,s==-1为降
while(1)
{
cout<<"/ninput matrix row N(N>=2): ";
cin>>n;
cout<<endl;
if(n>=2)
break;
}
m=n*n;
x1=0;y1=0;x2=n;y2=n;
if(n%2==0)
{j=n-1;y2=n-1;s=1;}
else
{i=n-1;y1=1;s=-1;}
while(1)
{
if(s==1)
{
for(i;i<x2;i++)
a[j]=m--;
i--;j--;x2--;
for(j;j>=y1;j--)
a[j]=m--;
j++;i--;y1++;
s=-1;
}
else
{
for(i;i>=x1;i--)
a[j]=m--;
i++;j++;x1++;
for(j;j<y2;j++)
a[j]=m--;
j--;i++;y2--;
s=1;
}
if(m<1)
break;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<setw(4)<<setiosflags(ios::left)<<a[j];
cout<<endl;
}
cout<<endl;
}
八皇后问题
生成各种矩阵是竞赛时经常考的一种题目,如何用C语言或C++生成以下形式几种矩阵:
第一种矩阵:
1 2 9 10
4 3 8 11
5 6 7 12
16 15 14 13
第二种矩阵蛇形)
1 2 6 7
3 5 8 13
4 9 12 14
10 11 15 16
第三种矩阵:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
第四种矩阵:
7 6 5 16
8 1 4 15
9 2 3 14
10 11 12 13
规律提示:
1.1->2 9->10
4<-3 8 11
5->6->7 12
16<-15<-14<-13
2.每个左上三角的数都是连续的
3.一个回旋阵,从外到里是连续的。
4.同样是回旋,从里到外是连续的。
第一种矩阵算法:
#include<iostream.h>
#include<iomanip.h>
void main()
{
const int N=20;
int i=0,j=0,a[N][N];
int lap=1,m=1,n;
while(1)
{
cout<<"/ninput matrix row N(N>=2): ";
cin>>n;
cout<<endl;
if(n>=2) break;
}
a[j]=m++;
lap++;
while(lap<=n)
{
if(lap%2==0)
{
for(j++;i<lap;i++)
a[j]=m++;i--;
for(j--;j>=0;j--)
a[j]=m++;j++;
}
else
{
for(i++;j<lap;j++)
a[j]=m++;j--;
for(i--;i>=0;i--)
a[j]=m++;i++;
}
lap++;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<setw(4)<<setiosflags(ios::left)<<a[j];
cout<<endl;
}
cout<<endl;
}
第二种矩阵算法:(蛇形)
#include<iostream.h>
#include<iomanip.h>
void main()
{
const int MAXLEN=10;
int nLen;
int nSnake[MAXLEN][MAXLEN];
do
{
cout<<"/ninput an integer less then "<<MAXLEN<<": ";
cin>>nLen;
cout<<endl;
}while(nLen>MAXLEN);
int i=0,j=0,s=1,nNum=1;
//s标记升降方向,斜向上为升(s==1),斜向下为降(s==-1)
while(1)
{
if(s==1)
{
nSnake[j]=nNum;
if(i-1<0)
{
if(j+1==nLen)
i++;
else
j++;
s=-1;
}
else
if(j+1==nLen)
{
i++;
s=-1;
}
else
{
i--;
j++;
}
}
else
{
nSnake[j]=nNum;
if(j-1<0)
{
if(i+1==nLen)
j++;
else
i++;
s=1;
}
else
if(i+1==nLen)
{
j++;
s=1;
}
else
{
i++;
j--;
}
}
nNum++;
if(nNum>nLen*nLen)
break;
}
for(i=0;i<nLen;i++)
{
for(j=0;j<nLen;j++)
cout<<setw(4)<<setiosflags(ios::left)<<nSnake[j];
cout<<endl;
}
cout<<endl;
}
第三种矩阵算法:
#include<iostream.h>
#include<iomanip.h>
void main()
{
const int N=20;
int i=0,j=0,a[N][N],n;
int m=1,x1,x2,y1,y2,s=1;
//x1,x2,y1,y2为上、下、左、右边界
//s标记数组元素升降,s==1为升,s==-1为降
while(1)
{
cout<<"/ninput matrix row N(N>=2): ";
cin>>n;
cout<<endl;
if(n>=2)
break;
}
x1=0;y1=0;x2=n;y2=n;
while(1)
{
if(s==1)
{
for(j;j<y2;j++)
a[j]=m++;
j--;i++;y2--;
for(i;i<x2;i++)
a[j]=m++;
i--;j--;x2--;
s=-1;
}
else
{
for(j;j>=y1;j--)
a[j]=m++;
j++;i--;y1++;
for(i;i>=x1+1;i--)
a[j]=m++;
i++;j++;x1++;
s=1;
}
if(m>n*n)
break;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<setw(4)<<setiosflags(ios::left)<<a[j];
cout<<endl;
}
cout<<endl;
}
第四种矩阵算法:
#include<iostream.h>
#include<iomanip.h>
void main()
{
const int N=20;
int i=0,j=0,a[N][N],n;
int m,x1,x2,y1,y2,s;
//x1,x2,y1,y2为上、下、左、右边界
//s标记数组元素升降,s==1为升,s==-1为降
while(1)
{
cout<<"/ninput matrix row N(N>=2): ";
cin>>n;
cout<<endl;
if(n>=2)
break;
}
m=n*n;
x1=0;y1=0;x2=n;y2=n;
if(n%2==0)
{j=n-1;y2=n-1;s=1;}
else
{i=n-1;y1=1;s=-1;}
while(1)
{
if(s==1)
{
for(i;i<x2;i++)
a[j]=m--;
i--;j--;x2--;
for(j;j>=y1;j--)
a[j]=m--;
j++;i--;y1++;
s=-1;
}
else
{
for(i;i>=x1;i--)
a[j]=m--;
i++;j++;x1++;
for(j;j<y2;j++)
a[j]=m--;
j--;i++;y2--;
s=1;
}
if(m<1)
break;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<setw(4)<<setiosflags(ios::left)<<a[j];
cout<<endl;
}
cout<<endl;
}
八皇后问题
通过创建一个8元素数组queenlist,递归函数placeQueen()具体执行此回溯算法。此数组的每个索引值都对应着棋盘上的一列,queenlist[col]值就是皇后所处的安全行数row。下面程序声明一个棋盘board,再使用setQueens()函数确定皇后再棋盘上8个安全位置。最后调用drawBoard()函数再棋盘上显示答案。
//文件:prg15——6.cpp
//此程序可以解决八皇后问题。程序提示用户输入皇后在0列的起始行并调用递归函数
//queens()确定是否有解决方案。如果有则将皇后的位置传到chessboard对象board
//并调用其drawBoard()函数显示皇后的布置。
#include<iostream.h>
#include”d_queens.h”
using namespace std;
int main()
{
int row;
vector<int>queenlist(8);
chessboard board;
//为0列皇后输入起始行
cout<<”Enter row for queen in column 0:”;
cin>>row;
cout<<endl;
//查看是否有解决方案
if (queens(queenlist, row))
{
board.setQueens(queenlist);
//显示解决方案
board.drawBoard();
}
else
cout<<”No solution”<<endl;
return 0;
}
第一次运行结果
0 1 2 3 4 5 6 7
0 Q
1 Q
2Q
3 Q
4 Q
5 Q
6 Q
7 Q
第二次运行结果
0 1 2 3 4 5 6 7
0 Q
1 Q
2 Q
3
4 Q
5Q Q
6 Q
7 Q 费尔马“二平方”素数
//文件:prg15——6.cpp
//此程序可以解决八皇后问题。程序提示用户输入皇后在0列的起始行并调用递归函数
//queens()确定是否有解决方案。如果有则将皇后的位置传到chessboard对象board
//并调用其drawBoard()函数显示皇后的布置。
#include<iostream.h>
#include”d_queens.h”
using namespace std;
int main()
{
int row;
vector<int>queenlist(8);
chessboard board;
//为0列皇后输入起始行
cout<<”Enter row for queen in column 0:”;
cin>>row;
cout<<endl;
//查看是否有解决方案
if (queens(queenlist, row))
{
board.setQueens(queenlist);
//显示解决方案
board.drawBoard();
}
else
cout<<”No solution”<<endl;
return 0;
}
第一次运行结果
0 1 2 3 4 5 6 7
0 Q
1 Q
2Q
3 Q
4 Q
5 Q
6 Q
7 Q
第二次运行结果
0 1 2 3 4 5 6 7
0 Q
1 Q
2 Q
3
4 Q
5Q Q
6 Q
7 Q 费尔马“二平方”素数
除了2这个特别的素数外,所有的素数都可以分成两类:第一类是被4除余1的素数,如5,13,17,29,37,41;第二类是被4除余3的素数,如3,7,11,19,23,31。第一类素数都能表示成两个整数的平方和(第二类不能),例如:5=1*1+2*2、13=2*2+3*3、17=1*1+4*4、29=2*2+5*5...这就是著名的费尔马“二平方”定理。有趣的是:上述等式右侧的数有的又恰恰是两个素数的平方,如13、29,我们就把这样的素数叫作费尔马“二平方”素数,即是如果一个素数能够表示成两个素数的平方和的形式,例如:F=X*X+Y*Y (1),其中F、X、Y都是素数,它就是费尔马“二平方”素数。
编程思路:
本文拟用C++编程,求42亿之内(本人只算了10万以内的)的费尔马“二平方”素数。如果按定义从左向右,先求一个素数F,然后再去找相应的素数X、Y,工作量重复太大。我们可以对上述公式进行分析:
1、左侧素数F肯定是奇数,那么右侧两个素数的和也应该是奇数,所以X和Y为一奇一偶(奇数的平方还是奇数,偶数的平方还是偶数)。X、Y要求是素数,而既是偶数又是素数的数只有一个——2,这样我们就可以确定其中一个为2(这里设X=2)。所以(1)式可以简化为:F=2*2+Y*Y (2),费尔马“二平方”素数的表示形式是惟一的。
2、按(2)式由大到小找素数Y,计算出加上4(2*2)后是否等于F,判断其是否素数。
3、求出素数Y后将其保存起来,在判断其它数是否素数时可直接用已求出的素数去除,如此反复。
算法源代码如下:
#include<iostream.h>
#include<iomanip.h>
unsigned int a[10000],n=0,c=0;
//prime array,match counter,array counter
void ScreenOut(unsigned long int prime)
{
unsigned int p;
for(p=c-1;p>0;p--) //from the front one
if(prime==(a[p]*a[p]+4))
{
//cout<<'/n';
cout<<setw(5)<<prime<<" = 2*2 + "<<setw(3)
<<a[p]<<" * "<<setw(3)<<a[p]<<endl;
n++;
}
}
void main()
{
unsigned long int i,count,quantity=100000;
int judgement; //if the number is prime,assign 1
a[0]=2;
for(count=3;count<quantity;count+=2)
{//because odd,jump 2 steps once
judgement=1; //assign 1 every cycle
for(i=3;i<count/2;i++)
{
if(count%i==0)
{
judgement=0;
break;
}
}
if(judgement)
{
a[++c]=count; //if prime,assign to array
ScreenOut(count);
}
}
cout<<"/ntotal of match: "<<n<<'/n'<<endl;
}
结论:
运行程序会发现,除“29=2*2+5*5”以外,算出来的所有的费尔马“二平方”素数个位数字都是3,相应Y的个位数字都是3或7。费尔马“二平方”素数分布(修改程序中变量x的值得到)也很耐人寻味...(部分省略)
费尔马“二平方”素数太少了,40亿内才718个(本人的电脑CPU慢,只算了10万以内的,符合条件的也就只有20个),千万分之二还不到呢。随着数的范围的增大,似乎越来越稀少,但再往后永远是这样吗?会不会在某个范围内反而又稠密起来呢?费尔马“二平方”素数是无穷多个呢,还是有限多个呢?如果是有限个,又是多少个呢?最大的一个又是什么数呢?这些问题的证明可能很简单,也许很复杂,真说不定会成为像“哥德巴赫猜想”那样的谜呢!
编程思路:
本文拟用C++编程,求42亿之内(本人只算了10万以内的)的费尔马“二平方”素数。如果按定义从左向右,先求一个素数F,然后再去找相应的素数X、Y,工作量重复太大。我们可以对上述公式进行分析:
1、左侧素数F肯定是奇数,那么右侧两个素数的和也应该是奇数,所以X和Y为一奇一偶(奇数的平方还是奇数,偶数的平方还是偶数)。X、Y要求是素数,而既是偶数又是素数的数只有一个——2,这样我们就可以确定其中一个为2(这里设X=2)。所以(1)式可以简化为:F=2*2+Y*Y (2),费尔马“二平方”素数的表示形式是惟一的。
2、按(2)式由大到小找素数Y,计算出加上4(2*2)后是否等于F,判断其是否素数。
3、求出素数Y后将其保存起来,在判断其它数是否素数时可直接用已求出的素数去除,如此反复。
算法源代码如下:
#include<iostream.h>
#include<iomanip.h>
unsigned int a[10000],n=0,c=0;
//prime array,match counter,array counter
void ScreenOut(unsigned long int prime)
{
unsigned int p;
for(p=c-1;p>0;p--) //from the front one
if(prime==(a[p]*a[p]+4))
{
//cout<<'/n';
cout<<setw(5)<<prime<<" = 2*2 + "<<setw(3)
<<a[p]<<" * "<<setw(3)<<a[p]<<endl;
n++;
}
}
void main()
{
unsigned long int i,count,quantity=100000;
int judgement; //if the number is prime,assign 1
a[0]=2;
for(count=3;count<quantity;count+=2)
{//because odd,jump 2 steps once
judgement=1; //assign 1 every cycle
for(i=3;i<count/2;i++)
{
if(count%i==0)
{
judgement=0;
break;
}
}
if(judgement)
{
a[++c]=count; //if prime,assign to array
ScreenOut(count);
}
}
cout<<"/ntotal of match: "<<n<<'/n'<<endl;
}
结论:
运行程序会发现,除“29=2*2+5*5”以外,算出来的所有的费尔马“二平方”素数个位数字都是3,相应Y的个位数字都是3或7。费尔马“二平方”素数分布(修改程序中变量x的值得到)也很耐人寻味...(部分省略)
费尔马“二平方”素数太少了,40亿内才718个(本人的电脑CPU慢,只算了10万以内的,符合条件的也就只有20个),千万分之二还不到呢。随着数的范围的增大,似乎越来越稀少,但再往后永远是这样吗?会不会在某个范围内反而又稠密起来呢?费尔马“二平方”素数是无穷多个呢,还是有限多个呢?如果是有限个,又是多少个呢?最大的一个又是什么数呢?这些问题的证明可能很简单,也许很复杂,真说不定会成为像“哥德巴赫猜想”那样的谜呢!
无厘头字母题
输入一系列单字,直到文件尾,将每个字转换为Pig-latin语,如果单字以辅音字母开头,则将其第一个字符移到最后一个位置并在结尾增加"ay"。如果单字是以元音字母开头的,则直接在尾部加上"ay"。列如:
输入:this is simple
输出:histay isay implesay
# include <iostream>
# include <cstdlib>
# include <cstring>
using namespace std;
void changeWord(char* a, char* b);
int yWordcmp(char a);
int main()
{
const int SIZE = 50;
char iWord[SIZE];
char oWord[SIZE];
for (int i = 0; i<SIZE; i++)
{
iWord[0]=NULL;
oWord[0]=NULL;
}
cout<<"输入要转化 Pig-latin 语:/n";
cin.getline(iWord,SIZE);
changeWord(iWord,oWord);
cout<<"/n转换结果:/n"<<oWord<<endl;
system("pause");
return 0;
}
void changeWord(char* a, char* b)
{
char c = NULL;
while (*a != NULL)
{
while (! isalpha(*a))
*b++ = *a++;
c = yWordcmp(*a)? NULL : *a++;
while (isalpha(*a))
*b++ = *a++;
if(c) *b++ = c;
*b++ = 'a';
*b++ = 'y';
}
}
int yWordcmp(char a)
{
char yWord[5] = {'a','e','u','i','o'};
for (int i =0; i<5; i++)
{
if ((a == yWord)||(a == yWord-32))
return 1;
}
return 0;
}
输入:this is simple
输出:histay isay implesay
# include <iostream>
# include <cstdlib>
# include <cstring>
using namespace std;
void changeWord(char* a, char* b);
int yWordcmp(char a);
int main()
{
const int SIZE = 50;
char iWord[SIZE];
char oWord[SIZE];
for (int i = 0; i<SIZE; i++)
{
iWord[0]=NULL;
oWord[0]=NULL;
}
cout<<"输入要转化 Pig-latin 语:/n";
cin.getline(iWord,SIZE);
changeWord(iWord,oWord);
cout<<"/n转换结果:/n"<<oWord<<endl;
system("pause");
return 0;
}
void changeWord(char* a, char* b)
{
char c = NULL;
while (*a != NULL)
{
while (! isalpha(*a))
*b++ = *a++;
c = yWordcmp(*a)? NULL : *a++;
while (isalpha(*a))
*b++ = *a++;
if(c) *b++ = c;
*b++ = 'a';
*b++ = 'y';
}
}
int yWordcmp(char a)
{
char yWord[5] = {'a','e','u','i','o'};
for (int i =0; i<5; i++)
{
if ((a == yWord)||(a == yWord-32))
return 1;
}
return 0;
}