话说从第4题一直鸽到第100题, 我还真是鸽的可以。。。
做题用时:2小时15分钟
- PATA1100 火星数字
题目大意:给出13进制数的火星字符(string型)写出其10进制的数字,或者给出10进制数字写出其火星字符形式。
思路:本身不难,就是单纯的进制转换加模拟,主要注意的一点是正好可以被13整除的数字例如13,26等,是单纯的用10进制火星字符表示而不要加上“tret”, 这一点虽然在题目里没有明确说,但是样例中最后一个写的很清楚。我一开始就是没看清这点导致2,4(大概)两个测试点没有通过 (=+= )
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
const int maxn=110;
int N;
string num10[15]={"zero","tam","hel","maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mer", "jou"};
string num1[15]={"tret","jan", "feb", "mar", "apr", "may", "jun", "jly", "aug", "sep", "oct", "nov", "dec"};
void getnum(string x){
if(x[0]>='0'&&x[0]<='9'){
int num=0;
for(int i=0;i<x.size();i++){
num+=x[i]-'0';
num*=10;
}
num/=10;
if(num>12&&num%13!=0) cout<<num10[num/13]<<" "<<num1[num%13];
else if(num<=12) cout<<num1[num];
else cout<<num10[num/13];
}
else{
if(x.size()==7){
string a=x.substr(0,3);
string b=x.substr(4,3);
int aa,bb;
for(int i=1;i<=12;i++){
if(num10[i]==a) aa=i;
}
for(int i=1;i<=12;i++){
if(num1[i]==b) bb=i;
}
cout<<aa*13+bb;
}
else if(x.size()==8){
string a=x.substr(0,3);
int aa;
for(int i=1;i<=12;i++){
if(num10[i]==a) aa=i;
}
cout<<aa*13;
}
else if(x.size()==3){
for(int i=1;i<=12;i++){
if(num1[i]==x) cout<<i;
}
for(int i=1;i<=12;i++){
if(num10[i]==x) cout<<i*13;
}
}
else if(x.size()==4){
cout<<0;
}
}
}
int main(){
cin>>N;getchar();
for(int i=0;i<N;i++){
string x;
getline(cin,x);
getnum(x);
cout<<endl;
}
}
注意点: getline接受带有空格的字符串,也可以用scanf("%[^\n]",%s)的写法用字符数组接收,同时要注意不论哪种写法,前面都要用getchar()接受之前的换行符。
- PAT1101 模拟快排
题目大意:给出一个序列,查找符合从左边其最大,从右边其最小的条件,并输出
思路:开一个结构体,存储左边起的最大值和右边起的最小值,因此要遍历三次
代码:`
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=100010;
struct Num{
int left,right;
int data;
}num[maxn];
int N;
int main(){
cin>>N;
int mmax=0,mmin=0x3fffffff;
for(int i=0;i<N;i++){
int temp;scanf("%d",&temp);
if(temp>mmax) mmax=temp;
num[i].data=temp;
num[i].left=mmax;
}
for(int i=N-1;i>=0;i--){
if(num[i].data<mmin) mmin=num[i].data;
num[i].right=mmin;
}
vector<int> ans;
for(int i=0;i<N;i++){
if(num[i].data==num[i].left&&num[i].data==num[i].right){
ans.push_back(num[i].data);
}
}
cout<<ans.size()<<endl;
for(int i=0;i<ans.size();i++){cout<<ans[i];if(i!=ans.size()-1) cout<<" ";}
cout<<endl;
}
25分最水的几个题之一
- PAT1102 反转树
题目大意:给出一个树,反转并输入层序遍历和中序遍历
思路:比较简单,层序改为现把右子树入队,中序改为现递归右子树即可。不过本英语渣渣把Invert看成了Insert,所以一开始理解成了插入树,幸好有样例给排雷。要不然又得硬刚1小时,然后全错做下一题 =。=
Invert (使)倒转,颠倒,倒置
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
using namespace std;
const int maxn=10010;
struct Node{
int data,left,right;
}node[maxn];
int N;
bool visit[maxn];
int cut=0,cnt=0;
void dfs(int root){
queue<int> q;
q.push(root);
while(!q.empty()){
int now=q.front();
if(node[now].right!=-1) q.push(node[now].right);
if(node[now].left!=-1) q.push(node[now].left);
cout<<now;if(cnt++!=N-1) cout<<" ";
q.pop();
}
}
void inorder(int root){
if(node[root].right!=-1) inorder(node[root].right);
cout<<root; if(cut++!=N-1) cout<<" ";
if(node[root].left!=-1) inorder(node[root].left);
return;
}
int main(){
cin>>N;
for(int i=0;i<N;i++){
node[i].data=i;
char tempa,tempb;
cin>>tempa>>tempb;
if(tempa=='-') node[i].left=-1;else {node[i].left=tempa-'0';visit[tempa-'0']=true;}
if(tempb=='-') node[i].right=-1;else {node[i].right=tempb-'0';visit[tempb-'0']=true;}
}
int root=0;
for(int i=0;i<N;i++){ if(visit[i]==false) root=i;}
dfs(root); cout<<endl;
inorder(root);
}
理解题意后,就很水,假如英语不好又没有样例就是地狱难度
- PAT1102 整数分解问题
题目大意:给出N,k,p三个数,希望得到N被分解为k个数的p次幂的和的形式。如果结果不唯一,那么先按照和最大排序,再按照最先遇到的不相同的元素最大排序。
思路:这个题可以说是四个题里对我最有价值的一个题了,本质是BFS剪枝搜索,之后再加上排序,排序部分比较好理解,现根据和排序,再根据第一个不同的元素最大排序。 初学cmp函数的有一个误区,就是以为 return 返回的是一个固定形式,用什么排序返回的就应是什么数据类型的大小比较,但是其实并不是,cmp返回的只是这种情况下的bool值,情况就是函数的运行情况,大小关系就是遇到这种情况时,谁应该比较大,不用纠结为什么返回时候比较的类型和输入的类型为什么不一样的问题(关于这点的深入研究应该需要读读源码)PATA1038也与此相似,那个是一个贪心问题。 之后就是关于BFS的部分,自己大概花了快45分钟的时间找bug(幸好最后找到了) 主要问题在于
for(int i=start;i>=1;i--)
这一段,我一开始写的是
for(int i=start;pow(double(i),double(p))>=now;i--)
这样的剪枝其实错误的因为错误的理解了判断条件,只要i-- 之后仍然是很大的值就把从1-i这条路全部pass了,这里我希望的是continue的关系,而这么写成了break的关系。因此有了这个教训,希望下次能记住。 另外为了省时间,我写成了从大到小搜索,这样可以少一次排序。 不知道从小到大搜索会不会超时。
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int maxn=100010;
int N,k,p;
vector<int> ans[maxn];
vector<int> temp;
int num=0;
bool cmp1(int a,int b){
return a>b;
}
bool cmp(vector<int> a,vector<int> b){
int aa=0,bb=0;
for(int i=0;i<a.size();i++){aa+=a[i];}
for(int i=0;i<b.size();i++){bb+=b[i];}
if(aa!=bb) return aa>bb;
for(int i=0;i<a.size();i++){
if(a[i]!=b[i]) return a[i]>b[i];
}
}
void dfs(int now ,int re, int p,int start){
if(now<0||re==0&&now!=0||now==0&&re!=0){
//cout<<"now="<<now<<" "<<"re="<<re<<" ";for(int i=0;i<temp.size();i++) cout<<temp[i]<<" ";cout<<endl;
return;
}
if(re==0&&now==0){
sort(temp.begin(),temp.end(),cmp1);
int x=0;
//for(int i=0;i<k;i++) cout<<temp[i]<<" ";cout<<endl;
//for(int i=0;i<k;i++) x+=pow(double(temp[i]),double(p));
//if(x==N)
ans[num++]=temp;
return;
}
for(int i=start;i>=1;i--){
temp.push_back(i);
//cout<<now-pow(double(i),double(p))<<endl;
dfs(now-pow(double(i),double(p)),re-1,p,i);
temp.pop_back();
}
}
int main(){
scanf("%d%d%d",&N,&k,&p);
int st=0;
for(int i=N;i>0;i--){if(pow(double(i),double(p))<=N) {st=i;break;}}
dfs(N,k,p,st);
if(num==0) {printf("Impossible");return 0;}
sort(ans,ans+num,cmp);
printf("%d = ",N);
for(int i=0;i<k;i++){
printf("%d^%d",ans[0][i],p);
if(i!=k-1) printf(" + ");
}
//for(int j=0;j<num;j++){
// printf("%d = ",N);
// for(int i=0;i<k;i++){
// printf("%d^%d",ans[j][i],p);
// if(i!=k-1) printf(" + ");
// }
// cout<<endl;
//}
}
反思: BFS搜索还是不熟悉,对于没有debug时候的排查错误也不熟练,不能很快得找出问题所在。