编程练习(1)

题目:

 1  有这样一个数字,ABCD  *  E  ==DCBA ,其中各个数字不相等,编写一个程序,计算出ABCD各代表什么数字。

 

#include 

int fun(int i,int j);
int reverse(int i);

int main()
{
    int i,j;
    for (i=1000; i<9999; i++)
        for(j=1; j<10; j++)
        {
            if(i*j==reverse(i)&&fun(i,j))
            {
                printf("%d\n",i);
                printf("*  %d\n",j);
                printf("-------\n");
                printf("%d\n\n",i*j);
            }
        }
    return 0;
}

int reverse(int i)//求i的倒置数
{
    int r=0;
    while(i)
    {
        r=r*10+i%10;
        i=i/10;
    }
    return r;
}

int fun(int i,int j)//判断是否有重复数字
{
    int buf[4],k=0;
    while(i)
    {
        buf[k]=i%10;
        i=i/10;
        k++;
    }
    if(buf[0]==buf[1])
        return 0;
    if(buf[0]==buf[2])return 0;
    if(buf[0]==buf[3])return 0;
    if(buf[0]==j)return 0;
    if(buf[1]==buf[2])return 0;
    if(buf[1]==buf[3])return 0;
    if(buf[1]==j)return 0;
    if(buf[2]==buf[3])return 0;
    if(buf[2]==j)return 0;
    if(buf[3]==j)return 0;
    return 1;
}

2  

 3对新婚夫妇参加婚礼,3个新郎为A、B、C,3个新娘为X、Y、Z.有人不知道谁和谁结婚,于是询问了6位新人中的3位,但听到的回答是这样的:A说他将和X结婚:X说她的未婚夫是C:C说他将和Z结婚。这人听后知道他们在开玩笑,全是假话。请编程找出谁将和谁结婚

#include 

int match(int i,int j,int k,char wife[]);
int main()
{
    char husband[3]= {'A','B','C'},wife[3]= {'X','Y','Z'};
    int i,j,k;
    for (i=0; i<3; i++)
        for (j=0; j<3; j++)
            for (k=0; k<3; k++)
                if(i!=j&&i!=k&&j!=k)
                {
                    if(match(i,j,k,wife))
                    {
                        printf("husband    wife\n");
                        printf("A----%c\n",wife[i]);
                        printf("B----%c\n",wife[j]);
                        printf("C----%c\n",wife[k]);
                    }
                }
    return 0;
}

int match(int i,int j,int k,char wife[])
{
    if(wife[i]=='X')return 0;
    if(wife[k]=='X')return 0;
    if(wife[k]=='Z')return 0;
    return 1;
}

3  分解质因数

#include

int isPrime(int a)//判断是否是质因数
{
    int i;
    for(i=2; i<=a-1; i++)
    {
        if(a%i==0)
            return 0;
    }
    return 1;
}

void PrimeFactor(int n)//分解质因数,并递归调用
{
    int i;
    if(isPrime(n))
        printf("%d",n);
    else
    {
        for(i=2; i<=n-1; i++)
        {
            if(n%i==0)
                printf("%d ",i);
            if(isPrime(n/i))
            {
                printf("%d ",n/i);
                break;
            }
            else
                PrimeFactor(n/i);
            break;
        }
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    PrimeFactor(n);
    return 0;
}

4 魔幻方阵,在n*n的矩阵中,填写n^2个数字,使得它的每一行,每一列以及两个对角线的和均相等

解法: 

#include 

int match(int i, int j, int k, int l, int m, int n, int o, int p, int q)
{
  if(i!=j && i!=k && i!=l && i!=m && i!=n && i!=o && i!=p && i!=q && j!=k && j!=l && j!=m && j!=n && j!=o && j!=p && j!=q && k!=l && k!=m && k!=n && k!=o && k!=p && k!=q && l!=m && l!=n && l!=o && l!=p && l!=q && m!=n && m!=o && m!=p && m!=q && n!=o && n!=p && n!=q && o!=p && o!=q && p!=q)
    return 1;
  else
    return 0;
}

int justic(int i, int j, int k ,int l, int m, int n, int o, int p, int q)
{
  if(i+j+k==l+m+n && i+j+k==o+p+q && i+l+o==j+m+p && i+l+o==k+n+q && i+m+q==k+m+o)
    return 1;
  else
    return 0;
}

void getMatrix()
{
  int i,j,k,l,m,n,o,p,q;
  for(i=1;i<=9;i++)
    for(j=1;j<=9;j++)
      for(k=1;k<=9;k++)
        for(l=1;l<=9;l++)
          for(m=1;m<=9;m++)
            for(n=1;n<=9;n++)
              for(o=1;o<=9;o++)
                for(p=1;p<=9;p++)
                  for(q=1;q<=9;q++)
                  {
                    if(match(i,j,k,l,m,n,o,p,q))
                      if(justic(i,j,k,l,m,n,o,p,q)){
                        printf("%d %d %d\n",i,j,k);
                        printf("%d %d %d\n",l,m,n);
                        printf("%d %d %d\n",o,p,q);
                        return;
                      }
                  }
}

int main(int argc, char *argv[])
{
  getMatrix();
  return 0;
}

另一个简单解法: 依次将1到N^2填入矩阵,填入的位置有如下规则确定。

 *第一个元素放在第一行中间一列 

*下一个元素存放在当前元素的上一行、下一列

 *如上一行、下一列已经有内容,则下一个元素存放在当前列的下一行。

 

5  将1~8这8个数字随机的填写到3*3的外层圆圈中,只剩下中间一个空圆圈。规定每次只能移动到空圆圈中,要求将数阵中的数字有序

本质就是排序,而且是带有交换性质的排序方法。我用的是选择排序,还可用冒泡排序。

#include
void Print(int m[]);
int  getstep(int m[]);
int main()
{
    int i , m[8];
    for(i=0 ; i<8 ; i++)
        scanf("%d",&m[i]);
    Print(m);
    printf("\n");
    getstep(m);
    Print(m);
    return 0;
}

void Print(int m[])
{
    printf("[%d]--[%d]--[%d]\n",m[0],m[1],m[2]);
    printf("|   %c  |  %c |\n" , 92 , 47);
    printf("[%d]--[  --[%d]\n",m[7],m[3]);
    printf("|   %c  |  %c |\n" , 47 , 92);
    printf("[%d]--[%d]--[%d]\n",m[6],m[5],m[4]);
}

int  getstep(int m[])
{
    int  i , j , temp;
    for (i =0 ; i<7 ; i++)
        for(j=0; j<7-i; j++)
            if(m[j]>m[j+1])
            {
                temp=m[j];
                m[j]=m[j+1];
                m[j+1]=temp;

            }
}

(6)
3个嫌疑犯在法官面前各执一词,甲说:乙在说谎:乙说:丙在说谎;丙说:甲乙两人都在说谎。法官为了难,甲乙丙三人到底谁在说谎,谁说的是真话?
【题目分析】
这是一道十分有趣的逻辑推理问题。解决这类逻辑推理问题最简单直观的方法是使用穷举法。甲乙丙三人中任何人所说的话无外乎有两种可能,即真和假。如果用1表示真,用0表示假,甲乙丙三人所说的话的真假情况限定在以下范围内。
甲乙丙
000
001……

#include

int main()
{
    int a,b,c;
    for (a=0; a<=1; a++)
        for (b=0; b<=1; b++)
            for (c=0; c<=1; c++)
            if((a&&!b ||  !a&&b)  &&  (b&&!c  ||  !b&&c)  &&  (c&&a+b==0  ||  !c&&a+b!=0))
            {
                printf(" 甲 told a %s\n",a?"truth":"lie");
                printf(" 乙 told a %s\n",b?"truth":"lie");
                printf(" 丙 told a %s\n",c?"truth":"lie");
            }
            return 0;
}

 

 

(7)验证四方定理

所有自然数最多只要4个数的平方和就可以表示,编写一个程序验证

#include

int mode_1(int n)   //N=a^2
{
    int i;
    for(i=1;i

 

 

这个解法想起来简单,不过太长。以下是另一种解法,这个解法比较巧,我是想不到,受教了。

 

# include 
# include 
int f(int n, int a[], int idx)
{
    int i;
    if(n==0) return 1;
    if(idx==4)  return 0;
    for( i=(int)sqrt(n); i>=1; i--)
    {
        a[idx] = i;
        if(i * i == n || f(n - i * i, a, idx + 1))  return 1;  //调用递归
    }
    return 0;

}
int main(int argc, char* argv[])
{
    for(;;)
    {
        int number;
        scanf("%d",&number);
        int a[] = {0,0,0,0};
        int r = f(number, a, 0);
        printf("%d: %d %d %d %d\n", r, a[0], a[1], a[2], a[3]);
    }
    return 0;
}

 

 

(8)编写一个程序,要求从一个整数序列中找出最小的元素,并用递归的方法实现

# include 
#define N 100

int GetMin(int a[] , int n)
{
    int v1, v2 , v3;
    if(n==1)
        return a[0];
    if(n%2==0)        //分情况讨论,判断整数的个数为奇数或偶数
    {
        v1=GetMin(a, n/2);
        v2=GetMin(a+n/2 , n/2);
        if(v1>v2)
            return v2;
        else
            return v1;
    }

    if(n%2!=0)
    {
        v1=GetMin(a, n/2);
        v2=GetMin(a+n/2+1 , n/2);
        v3=a[n/2];
        if(v1

 

(9)渔夫捕鱼问题
A、B、C、D、E这5个渔夫夜间合伙捕鱼,凌晨时都疲倦不堪,各自在河边的树丛中找地方睡着了。待日上三竿,渔夫A第一个醒来,他将鱼分作5份,把多余的一条扔回河中,拿自己的一份回家去了。渔夫B第二个醒来,也将鱼分作5份,扔掉多余的一条拿走自己的一份,接着C、D、E依次醒来,也都按同样的办法分鱼,问5个渔夫至少合伙捕了多少条鱼?试编程序算出

解决这个问题需要从最后一个渔夫入手,按照分鱼的原则,最后一次剩下的可能为6,11,16,21……加入为6,那D为8.5,显然是不合逻辑的。所以重新取E可能的值。

# include 


#define MAX 1000

int main()
{
    int last_fish;
    int s;
    int flag;
    int i , n;
    for(n=1; n

(10)在选美比赛的现场,有一批选手参加比赛,比赛的规则是最后得分越高,名次越低,
当比赛结東时,要在现场按照选手的出场顺序(即选手的序号)宣布最后得分和最后名
次,获得相同分数的选手具有相同的名次,名次连续编号,不用考虑同名次的选手人数,
例如:
选手序号为:
1,2,3,4,5,6,7
选手得分为
5,3,4,7,3,5,6
名次为

3,1,2,5,1,3,4

这个问题不能用排列解决,应结合结构体,组成结构体数组

# include 

typedef struct player
{
    int num;
    int score;
    int rand;
} P;

void sortScore(P psn[],int n)
{
    int i,j;
    P temp;
    for(i=0;ipsn[j+1].score)
        {
            temp=psn[j];
            psn[j]=psn[j+1];
            psn[j+1]=temp;
        }
    }
}

void setRand(P psn[] , int n)
{
    int i,j=2;
    psn[0].rand=1;
    for(i=1;ipsn[j+1].num)
        {
            tmp=psn[j];
            psn[j]=psn[j+1];
            psn[j+1]=tmp;
        }
    }
}


void sortRand(P psn[],int n)
{
    sortScore(psn,n);//以分数为关键字排列
    setRand(psn,n);//按照分数拍名次
    sortNum(psn,n);//按照序号重新排列
}

int main()
{
    P psn[7]= {{1,5,0},{2,3,0},{3,4,0},{4,7,0},{5,3,0},{6,5,0},{7,6,0}};
    int i;
    sortRand(psn , 7);
    printf("num  score  rand    \n");
    for(i=0;i<7;i++)
    {
        printf("%d%6d%6d\n",psn[i].num, psn[i].score, psn[i].rand);
    }
    return 0;
}

(11)顺序表的就地逆置

利用原表的存储空间将顺序表逆置

#include
#include
#define MAXSIZE 10

typedef struct
{
    int *base;
    int length;
} sqlist;

void reverse(sqlist *l)//逆置
{
    int low=0 , high=l->length-1;
    int buf , i;
    for(i=0;ilength/2 ; i++)
    {
        buf=l->base[low];
        l->base[low] = l->base[high];
        l->base[high]= buf;
        low++;
        high--;
    }
}

int main()
{
    int  a,i=0;
    sqlist l;
    l.base=(int *)malloc(sizeof(int)*MAXSIZE);
    l.length=0;

    scanf("%d",&a);
    while(i<=9&&a!= -1)
    {
        l.base[i]=a;
        l.length++;
        i++;
        scanf("%d",&a);
    }

    reverse(&l);
    for(i=0; i

 

你可能感兴趣的:(数据结构)