第一次完整做完一套pat题目,没有限时,分数分别为25+25+24+15
上学期刚学的算法,然而现在DFS都不会写了确实是没想到,二叉树相关的基础操作还是挺扎实(感谢数据结构的屈老师)
下面附上这几题的代码和简要思路:
第一题就是求左边的数都比他小,同时右边的数都比他大的数的个数,遍历两次数组即可,时间复杂度O(n),两层循环会超时
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n],maxleft[n],minright[n];
int i,j;
for(i=0;i<n;i++)
{
cin>>a[i];
}
vector<int> b;
maxleft[0]=a[0];
minright[n-1]=a[n-1];
for(i=1;i<n;i++)
{
maxleft[i]=max(maxleft[i-1],a[i]);
minright[n-i-1]=min(minright[n-i],a[n-i-1]);
}
for(i=0;i<n;i++)
{
if(a[i]==maxleft[i]&&a[i]==minright[i])
{
b.push_back(a[i]);
}
}
cout<<b.size()<<endl;
for(i=0;i<b.size();i++)
{
if(i!=b.size()-1)cout<<b[i]<<' ';
else cout<<b[i]<<endl;
}
}
第二题二叉树的基本操作
mark一下关于stl库中queue容器的pop,front,push操作,分别为出队,取队首元素和入队。
#include<bits/stdc++.h>
using namespace std;
bool flag;
struct node
{
int n;
node *lc=NULL;
node *rc=NULL;
node *f=NULL;
};
void bianli2(node *p)
{
if(p==NULL)
return;
bianli2(p->lc);
if(flag!=0)
cout<<' '<<p->n;
else{
cout<<p->n;
flag=1;
}
bianli2(p->rc);
}
int main()
{
int n;
cin>>n;
int i;
char l,r;
node tree[n];
for(i=0; i<n; i++)
{
tree[i].n=i;
}
for(i=0; i<n; i++)
{
cin>>l>>r;
if(r!='-')
{
tree[i].lc=&tree[r-'0'];
tree[r-'0'].f=&tree[i];
}
if(l!='-')
{
tree[i].rc=&tree[l-'0'];
tree[l-'0'].f=&tree[i];
}
}
node *p=&tree[0];
while(p->f!=NULL)
{
p=p->f;
}
node *root=p;
if(n==1)
{
cout<<0<<endl;
cout<<0<<endl;
}
if(n==0)
{
cout<<endl;
cout<<endl;
}
if(n>1)
{
flag=0;
queue<node*> q;
q.push(root);
node *p2;
while(q.size()!=0)
{
p2=q.front();
q.pop();
if(flag==0)
{
cout<<p2->n;
flag=1;
}
else cout<<' '<<p2->n;
if(p2->lc!=NULL)
{
q.push(p2->lc);
}
if(p2->rc!=NULL)
{
q.push(p2->rc);
}
}
cout<<endl;
flag=0;
bianli2(root);
}
}
第三题是DFS,有两个测试点超时,扣了六分
本题还有一个坑就是pow(x,y)参数和返回值均为double类型,会存在精度问题(无法精确表示整数)
所以我自己写的幂次函数
后补:
超时的原因是item数组插的元素太多,实际上最大也只需要n-k+1这么大的幂,所以应把for循环条件改为pow(i,p)<n-k+1
测试点2卡住的原因是和相同时未选取字典序更大的解,将nkp函数中
if(k==0)内的result>maxsum改为>=即可,因为我们是按字典序从小到大遍历的!
代码已修改:
#include<bits/stdc++.h>
using namespace std;
vector<int> flag;
vector<int> item;
int maxsum=0;
vector<int> maxflag;
void nkp(int n,int k,int p,int maxt,int result) //n剩余的值,还有k位,p的值,允许幂次最大值
{
int i;
if(n<0) return;
if(k==0)
{
if(result)
if(n==0)
{
if(result>maxsum)
{
maxsum=result;
maxflag=flag;
}
}
return ;
}
else
{
for(i=0; i<item.size()&&i<maxt+1; i++)
{
flag.push_back(i+1);
nkp(n-item[i],k-1,p,i,result+i+1);
flag.pop_back();
}
return;
}
}
int p0w(int i,int j)
{
int k,p=i;
for(k=1;k<j;k++)
{
i=i*p;
}
return i;
}
int main()
{
int n,k,p,i,op=1;
cin>>n>>k>>p;
if(n>k){
for(i=1; p0w(i,p)<n-k+2; i++)
{
item.push_back(p0w(i,p));
}
}
else if(n==k)
{
item.push_back(1);
}
else{
cout<<"Impossible"<<endl;
return 0;
}
nkp(n,k,p,item.size()-1,0);
if(maxsum==0)
cout<<"Impossible"<<endl;
else
{
cout<<n<<" = "<<maxflag[0]<<"^"<<p;
for(i=1; i<k; i++)
{
cout<<" + "<<maxflag[i]<<"^"<<p;
}
cout<<endl;
}
}
第四题巨坑。。思想很简单,每个数的出现次数很容易就可以算出,但是又是double类型!无法精确表示的这些小数,误差累积起来,会导致最后的结果误差
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,i;
cin>>n;
double a[n];
long long b[n];
long long sum=0;
for(i=0;i<n;i++)
{
cin>>a[i];
sum+=(long long)((a[i]*1000)*(i+1)*(n-i));
}
printf("%.2f",sum/1000.0);
}
为什么是1000,我也很迷惑,而且a[i]*1000和(i+1)(n-i)的顺序居然也有讲究。。。这两个测试点也错了
all in all,感受了一下pat的难度,更有信心了,这一个月要好好准备,争取一步到位