第1题
1.原题:假设平面上有1~N(x,y)个坐标点,编程判断这N(x,y)个点能组成多少个有效三角形。
问题分析:本题为一道基本编程题,要点就是判断三个点能构成三角形的条件
解决方案(思路): 三个点可以构成一个有效三角形等价于这三点不共线等价于这三个点围成的图形的面积不为0,而三角形的面积计算可以用行列式来表示,故可以转化为判断行列式的值是否为0
算法描述:通过定义两个浮点型数组x,y作为每一个点的横纵坐标,然后再代入行列式展开的结果中,判定其值是否为0,若不为0,则计数变量递增
源程序:
#include<stdio.h>
int main()
{
int n,i,j,k,t=0;
float x[1000],y[1000],s;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%f%f",&x[i],&y[i]);//读入每一个点的横纵坐标
}
for(i=0;i<n-2;i++)
{
for(j=i+1;j<n-1;j++)
{
for(k=j+1;k<n;k++)
{
s=0.5*(x[i]*y[j]+x[j]*y[k]+x[k]*y[i]-x[i]*y[k]-x[j]*y[i]-x[k]*y[j]);/*三角形面积行列式公式的展开
由于其正负与所选三个点的顺逆时针排列有关,故一般取绝对值,但是在这道题中并无影响*/
if(s!=0.0) t++;
}
}
}
printf("%d",t);
return 0;
}
第2题
2.原题:用整型数组表示10进制大整数(超过2^32的整数),数组的每个元素存储大整数的一位数字,实现大整数的加减法。
问题分析:高精度加法相对于减法要简单一点,加法只需要判断进位情况,而减法则需要判断借位情况和差的正负号。
解决方案(思路):在进行编程之前先寻找一些规律:对于高精度加法,两个大整数之和的位数最多是其中较大数的数位加一,再想办法解决进位问题即可;对于高精度减法,两个数的差的位数最大为较大数的数位(这是建立在被减数大于减数的基础下的,如果被减数小于减数,可以用减数减去被减数,然后再添加负号)。
下面开始编程,先考虑加法:以字符串的形式分两行输入两个数字串,分别将每一个数字字符转换成整数存储在两个不同的数组里面,开第三个数组,存储前面两个数组各位数字之和。然后开始对第三个数组进行修改:从个位开始,c[i]=c[i]%10,c[i+1]+=c[i]/10;掌握了加法的进位表示方法之后,减法的借位应该也就没有问题了,考虑到差的正负情况,我引入了一个标记flag,根据标记的取值情况判断两个数的大小,然后决定是否输入负号,此外,比较两个大整数大小的时候我另外定义了一个函数。
算法描述:定义比较高精度大小的函数,开两个字符数组进行大整数的输入,并记录其长度,再开四个整型数组,其中两个用来存储大整数的每一位,另外两个分别记录和与差。
源程序:
#include<stdio.h>
#include<string.h>
int max(int a,int b)//简单的max函数
{
if(a>b) return a;
else return b;
}
int compare(int a[],int b[])//判断大整数大小的函数
{
int i;
if(a[0]>b[0]) return 1;//此处a[0],b[0]分别表示两个大整数的位数,根据位数可简单比较
if(a[0]<b[0]) return -1;
for(i=a[0];i>0;i--)//位数相同时,从高位到低位依次进行判断
{
if(a[i]>b[i]) return 1;
if(a[i]<b[i]) return -1;
}
return 0;}
int main()
{
char m[100],n[100];
int a[101]={0},b[101]={0},c[102]={0},d[101]={0},i,t,flag;
scanf("%s%s",m,n);
a[0]=strlen(m),b[0]=strlen(n);
for(i=1;i<=a[0];i++)
{
a[i]=m[a[0]-i]-'0';
}//将字符数字转换为整型,存入数组,下面原理相同
for(i=1;i<=b[0];i++)
{
b[i]=n[b[0]-i]-'0';
}
t=max(a[0],b[0]);
for(i=1;i<=t;i++)
{
c[i]=a[i]+b[i];
}//先将两个大整数每一位的和存入一个新的数组,然后再进行具体操作
for(i=1;i<=t;i++)
{
c[i+1]+=c[i]/10;//进位处理
c[i]%=10;//确保新数组中的每一位都是一个数字(即不大于10)
}
if(c[t+1]>0) t++;//当产生的结果比原数中较大数的数位还要多一时,数位进行相应的更新
printf("高精度加法计算结果为:\n");
for(i=t;i>0;i--)
{
printf("%d",c[i]);
}
printf("\n");
flag=compare(a,b);//标记量
printf("高精度减法计算结果为:\n");
if(flag==0) printf("0");//两数相等时直接输出0即可
else if(flag==1)
{
for(i=1;i<=a[0];i++)
{
if(a[i]<b[i])
{
a[i+1]--;a[i]+=10;//借位操作
}
d[i]=a[i]-b[i];
}
while(d[a[0]]==0) a[0]--;//和加法类似,进行数位更新
for(i=a[0];i>0;i--)
{
printf("%d",d[i]);
}
}
else if(flag==-1)//a-b=-(b-a),基于上一个分支里面的操作,在输出前加一个负号即可
{
for(i=1;i<=b[0];i++)
{
if(a[i]>b[i])
{
b[i+1]--;b[i]+=10;
}
d[i]=b[i]-a[i];
}
while(d[b[0]]==0) b[0]--;
printf("-");
for(i=b[0];i>0;i--)
{
printf("%d",d[i]);
}
}
}