PAT甲级刷题实录——1002

原题

This time, you are supposed to find A+B where A and B are two polynomials.

Input Specification:

Each input file contains one test case. Each case occupies 2 lines, and each line contains the information of a polynomial:

\(K\ N_1\ a_{N_1}\ N_2\ a_{N_2}...N_K\ a_{N_K}\)

where K is the number of nonzero terms in the polynomial, \(N_i\) ​​ and \(a_{N_i}\) (i=1,2,⋯,K) are the exponents and coefficients, respectively. It is given that 1≤ K≤10,0≤ N​K​​<⋯

Output Specification:

For each test case you should output the sum of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate to 1 decimal place.

Sample Input:

2 1 2.4 0 3.2
2 2 1.5 1 0.5

Sample Output:

3 2 1.5 1 2.9 0 3.2

思路

一开始完全没搞明白题目在问什么,后来看了好几遍,再结合输入和输出的例子,才明白题目想问什么。其实把题目转换为数学式子就是用它规定的格式给你两个多项式,比如 \(y_1=ax+bx^2+cx^3,y_2=ix+jx^2+kx^3\) ,让你算出 \(y_1+y_2\) 并且用它规定的格式输出。像题目中给的案例输入的式子就是 \(y_1=2.4x+3.2,y_2=1.5x^2+0.5x\) ,输出的就是 \(y_3=1.5x^2+2.9x+3.2\)

首先面临的问题是该如何存储输入的数据,可以看到输入的数据主要有三种类型,第一种是每行的第一个数字,也就是每个式子包含的元素个数,这个很简单,我们用一个 int 类型去存储即可。还有两种类型分别代表指数和系数,并且两者是一一对应的,因此我的想法是用结构体存,因为有好几个元素,而且给定了元素个数,所以一开始我的想法是用结构体动态数组存储。

中间的运算过程我们暂且不管。确定了输入数据的存储方式,接下来应当确定输出数据的存储方式。一开始我想的还是结构体数组,但是这里出现了问题,我并不知道计算结果的式子中包含几个元素,也就无法确定数组的大小,当然后来发现题目里给定了元素个数的最大值,按照那个最大值乘以二就可以,但一开始我想的是用链表或者其他可变的数据结构存储,而且尽管这道题给定了个数范围,但在实际应用中很难会有给定的数值范围,必须考虑可变长度的数据结构。

经过一番搜寻,找到了 vector 这个神器,相当于可变长度的数组,而且使用方法非常方便。有了 vector,索性输入数据也用它存吧,因为动态数组还得 new 和 delete,比较麻烦。

我们已经有了两个 vector 存储结构体变量,并且可以实现遍历操作,接下来就要考虑算法了。这个算法其实非常类似二路归并排序最后合并过程的算法,如果不了解二路归并算法的同学可以先了解一下。基本思路如下:使用两个下标同时对两个 vector 进行比较和遍历,哪个 vector 中指向的元素的指数更大,则将这个元素添加到第三个 vector,也就是存储结果的 vector 中去,同时该元素所在的 vector 下标加 1;当两个元素的指数相等时,就把两个元素的系数加起来产生新的元素,并存储到第三个 vector 中去,同时前两个 vector 的下标都加 1(注意,这里存在一个问题,下文会讲到),代码如下:

#include 
#include 
using namespace std;

struct poly
{
    int exp;
    float coe;
};
int main()
{
    int a,b;
    cin>>a;
    vector poly1;
    vector poly2;
    vector sum;
    for(int i=0;i>p.exp>>p.coe;
        poly1.push_back(p);
    }
    cin>>b;
    for(int i=0;i>p.exp>>p.coe;
        poly2.push_back(p);
    }
    int i=0,j=0;

    while(ipoly2[j].exp)
        {
            sum.push_back(poly1[i]);
            i++;
        }
        else if(poly1[i].exp

一开始犯了很多低级错误,比如定义 i,j 是这样定义的 int i,j=0 ,结果就导致只给 j 赋了值,出来的结果也必定是错的,都没敢输入评测系统,因为本地调试就是错的。改掉了这个问题后,至少看起来对了,就输入评测系统试了试,但是还只是部分正确,后来重新看了一遍题,发现题目要求保留一位小数,但我没保留。原本我想用 c++ cout 输出的方式来保留一位小数的,但是网上查了一下还要添加头文件 iomanip ,还要用一个很复杂的语句 cout< ,我就放弃了,改用 c 语言 printf 的方式, %.1f 就行,非常简单粗暴,反正 C++ 是完全兼容 C 语言的。

但是改掉这些低级错误后,依然过不了评测系统,只是分数提高了一点,结果还是部分正确。这下我就真想不到问题出在哪里了。没办法,只好上网去看人家的做法,终于发现一个大问题,就是当两个指数相同的时候,如果两个系数正好相反,那么得出的元素应该被舍去而不是把系数 0 存储进结果。这下子豁然开朗,修改方法也很简单,只要在相加的时候加个判断语句就行。修改后的代码如下:

#include 
#include 
using namespace std;

struct poly
{
    int exp;
    float coe;
};
int main()
{
    int a,b;
    cin>>a;
    vector poly1;
    vector poly2;
    vector sum;
    for(int i=0;i>p.exp>>p.coe;
        poly1.push_back(p);
    }
    cin>>b;
    for(int i=0;i>p.exp>>p.coe;
        poly2.push_back(p);
    }
    int i=0,j=0;

    while(ipoly2[j].exp)
        {
            sum.push_back(poly1[i]);
            i++;
        }
        else if(poly1[i].exp

终于完全正确了,C++ 的执行效率还是快啊。

你可能感兴趣的:(PAT甲级刷题实录——1002)