(PTA记录)1002 A+B for Polynomials (25分)
题目内容:
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 N1 aN1 N2 aN2 … NK aNK
where K is the number of nonzero terms in the polynomial, Ni and aNi (i=1,2,⋯,K) are the exponents and coefficients, respectively. It is given that 1≤K≤10,0≤NK<⋯<N2<N1≤1000.
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
可能需要到的单词:
polynomials: 多项式的;
exponent: 指数,幂;
coefficient: 系数;
respectively: 分别得,各自得;
format: 格式;
accurate: 准确地;
decimal: 十进制地;
我的代码(由于本人目前水平不高,所以代码很小白,只在关键地方有注释,主要是记录期间遇到的问题):
通过率:100%;
#include <iostream>
#include <string>
#include <iomanip>
int main(){
int k1,k2,ex;
double co;
cin >> k1;
int e1[k1];
double c1[k1];
for(int i = 0;i < k1;i++){
cin >> ex;
e1[i] = ex;
cin >> co;
c1[i] = co;
}
cin >> k2;
int e2[k2];
double c2[k2];
for(int i = 0;i < k2;i++){
cin >> ex;
e2[i] = ex;
cin >> co;
c2[i] = co;
}
int count = k1 + k2,min = -1,v1 = 0,v2 = 0;
int out1[count];
double out2[count];
for(int i = k1 - 1;i >= 0;i--){
for(int j = k2 - 1;j >= 0;j--){
if(e1[i] != e2[j]){
/*这里是这样的,首先是让数组 e1和 e2倒序从他们的最小值开始比较,
先比较两个数组当前序列哪个小,再用小的和目前存在 out1里面的最小值比,
如果比 out1里面的最小值(即 min)小,添加到 out1,并更新 min的值
这个可以自己试一哈,我在草稿纸试了很多例子发现可行,就是倒序中找最小的放入*/
if(e1[i] >= e2[j] && e2[j] > min){
out1[v1++] = e2[j];
out2[v2++] = c2[j];
min = e2[j];
}else if(e2[j] > e1[i] && e1[i] > min){
out1[v1++] = e1[i];
out2[v2++] = c1[i];
min = e1[i];
}
}else{ //当幂相等时,上面的填入最小值仍生效
count--; //原来有的多项式的个数就要减去1
double s = c1[i] + c2[j]; //测试点0,1,2 错写int型
if(s != 0){ //测试点3,4,5,判断系数相加是否为0
out1[v1++] = e1[i];
out2[v2++] = s;
}else{
count--; //这里注意,如果系数为空了,没有这一项,count需要再减一次1
}
min = e1[i];
}
}
}
if(e1[0] > e2[0]){ //这个if-else语句就是当k1,k2个数不相等会有一个多出来,找到所有比mid大的,依次加入out就好了
for(int i = 0;i < k1;i++){
if(e1[i] > min){
out1[v1++] = e1[i];
out2[v2++] = c1[i];
}
}
}else{
for(int i = 0;i < k2;i++){
if(e2[i] > min){
out1[v1++] = e2[i];
out2[v2++] = c2[i];
}
}
}
if(count != 0){
cout<<count<<" ";
for(int i = v1 - 1;i >= 0;i--){ //out中的序数是倒着的,所以需要反过来
if(i == 0){ //以下两种输出方式均可。
//printf("%d %.1f",out1[i],out2[i]);
cout<<out1[i]<<" "<<setiosflags(ios::fixed)<<setprecision(1)<<out2[i];
}else{
//printf("%d %.1f ",out1[i],out2[i]);
cout<<out1[i]<<" "<<setiosflags(ios::fixed)<<setprecision(1)<<out2[i]<<" ";
}
}
}else{
cout<<"0"; //测试点6,没有任何项,输出0
}
return 0;
}
代码其实挺简单易懂的,但说实话我也看不下去,时间和空间复杂度太大了。。。好歹通过了(嘤嘤嘤)。
遇到问题及解决流程:
1.测试点0.1.2:
(注意double型和int型的使用和结果的输出)
首先我在解决了遇到的编译问题(。。。)后,只通过了一个测试点,就目前来看,那个测试点的记录中系数应该都是int型,所以通过了。然后我通过线上的c++编译器运行了一下我的代码,发现结果本应是2.9的地方却是2.0,于是我找到了我写的时候犯得一个小错误,在新建一个s使s等于幂相等的系数和的时候我竟然新建了一个int型。。。
2.测试点3.4.5:
(注意相等幂的两项系数和正好为0)
网上查找资料有提醒说会有幂相等的两个系数和为0的情况,此时需要删除该项,于是我加了和为0的判断,我以为解决了,其实并没有,因为疏忽了这个项删除后前面的计数(我这里是count)也应该减1。
3.测试点6:
(注意没有输入任何项)
在解决了3.4.5而6没通过时我本能的想到了可能是输入为空,于是我试了输入为空时输出为空和输出为“0,0”(我吐了),结果都不行,于是网上找了一个全通过的放上去试了一下,发现输出结果是“0”。所以后面加了个判断输出0。
以上便是我这道题在编写时遇到的问题,用以记录。
以下是网上找到的使用映射法的较优解:
#include <iostream>
#include <string>
#include <iomanip>
#include <stdio.h>
#include <string.h>
using namespace std;
int main(){
float hashT[1001];
memset(hashT,0,sizeof(hashT)); //初始化hashT
int k,cnt = 0;
for(int i = 0;i < 2;i++){
scanf("%d",&k);
int N;
float ai;
for(int j = 0;j < k;j++){
scanf("%d %f",&N,&ai);
hashT[N] += ai; //遇到幂相等的系数直接相加了
}
}
for(int i = 0;i < 1001;i++){
if(hashT[i] != 0){
cnt++;
}
}
printf("%d",cnt);
for(int i = 1000;i >= 0;i--){
if(hashT[i] != 0.0){
printf(" %d %.1f",i,hashT[i]);
}
}
return 0;
}
相比我的算法,在空间上该算法一定是优于我的,在时间上主要取决于n的大小,即k的个数,k越大使用映射法越好。