今年的2、3、4題比較簡單,尷尬的是第1題一點思路都沒有,甚至沒想起用暴力求解得點分,是這次PAT很大的遺憾。
我把考試時候的代碼貼在下面,本人代碼水平並不高,貼出來只為學習交流,不喜勿噴~
7-2 Merging Linked Lists (25 分)
思路:先區分長鏈短鏈,然后不斷循環,依次取長鏈中兩個點和短鏈中一個點加入到新鏈中,直到長鏈和短鏈都處理完。
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> using namespace std; const int maxn=100010; int n,m1,m2,k; int f1,f2; vector<int>v[3],ans; struct node{ int Address ,Data ,Next; }nodes[maxn]; void merge(int a,int b){//合並過程,此時滿足a>b int k1=0; int k2=0; int len2=v[b].size()-1; while(k1<v[a].size()||k2<v[b].size()){//若還有一個鏈沒處理完 if(k1<v[a].size()){ //將長鏈第一個點加到ans中 ans.push_back(v[a][k1]); k1++; } if(k1<v[a].size()){ //將長鏈第二個點加到ans中 ans.push_back(v[a][k1]); k1++; } if(k2<v[b].size()){ //將短鏈的一個點加到ans中 ans.push_back(v[b][len2-k2]); k2++; } } } int main(){ cin>>f1>>f2>>n; for(int i=0;i<n;++i){ int add; scanf("%d",&add); nodes[add].Address=add; scanf("%d%d",&nodes[add].Data,&nodes[add].Next); } int p1=f1;//遍歷第一條鏈 while(p1!=-1){ m1++; v[1].push_back(p1); p1=nodes[p1].Next; } int p2=f2;//遍歷第二條鏈 while(p2!=-1){ m2++; v[2].push_back(p2); p2=nodes[p2].Next; } if(m1>m2){//區分出長鏈與短鏈 merge(1,2); }else merge(2,1); for(int i=0;i<ans.size()-1;++i){ int u=ans[i]; printf("%05d %d %05d\n",nodes[u].Address,nodes[u].Data,nodes[ans[i+1]].Address); } int u=ans[ans.size()-1]; printf("%05d %d -1\n",nodes[u].Address,nodes[u].Data); return 0; }
7-3 Postfix Expression (25 分)
這個題我開始沒仔細研讀題目,直接按樹的中序遍歷方式進行輸出,發現不對后按照例子對中序遍歷進行修改,驚喜的是這樣居然就能AC了。
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <string> using namespace std; const int maxn=25; int n,m1,m2,k; int father[maxn]; struct node{ string data; int lchild,rchild; }nodes[maxn]; void inorder(int root){ printf("("); if(nodes[root].rchild!=-1&&nodes[root].lchild==-1){ cout<<nodes[root].data; if(nodes[root].rchild!=-1){ inorder(nodes[root].rchild); } }else{ if(nodes[root].lchild!=-1){ inorder(nodes[root].lchild); } if(nodes[root].rchild!=-1){ inorder(nodes[root].rchild); } cout<<nodes[root].data; } printf(")"); } int findFather(int x){ while(x!=father[x]){ x=father[x]; } return x; } int main(){ cin>>n; for(int i=1;i<=n;++i){ father[i]=i; } for(int i=1;i<=n;++i){ string str; cin>>nodes[i].data; scanf("%d%d",&nodes[i].lchild,&nodes[i].rchild); father[nodes[i].lchild]=father[nodes[i].rchild]=i; } int root=findFather(1); inorder(root); return 0; }
7-4 Dijkstra Sequence (30 分)
我個人感覺這道題目出的比較好,dijkstra模板可能大家都理解了,那種固定的做題方式大家也都會,而這道題是考到了對模板的理解。
剛開始我走了很多歪路,(主要是受之前做題慣性思維的影響,還在用dij+dfs之類的,當然也可以解,但不是很正的思路)
思路:在dijkstra過程中,從所有優化好路徑的點中取一個距離最小的點 u ,我們只需要判斷所給出的例子中那一步的值可以不可取做u就可以了,若可以取則繼續下一步判斷,若不能取則直接判NO。能不能取做u的標准是,d[u]是不是當前的最小值之一。
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <string> using namespace std; const int maxn=10010; const int inf=0x3fffffff; int nv,ne; struct node{ int w,v; }; vector<node>graph[maxn]; int d[maxn]; vector<int>check; bool vis[maxn]; bool flag; int p; bool dijkstra2(int root){ fill(d,d+maxn,inf); fill(vis,vis+maxn,false); d[root]=0; for(int i=1;i<=nv;++i){ int MIN=inf,u=-1; for(int j=1;j<=nv;++j){//關鍵代碼部分 if(vis[j]==false&&d[j]<MIN){ //出現最小值讓u取為它 MIN=d[j]; u=j; } else if(vis[j]==false&&d[j]==MIN){ //出現等於最小值,而且u是查詢的值 if(j==check[p])u=j; } } if(u!=check[p]||u==-1)return false; vis[u]=true; p++; if(p>=nv)return true; //關鍵部分代碼結束 for(int j=0;j<graph[u].size();++j){ int v=graph[u][j].v; if(vis[v]==false&&d[u]+graph[u][j].w<d[v]){ d[v]=d[u]+graph[u][j].w; } } } } int main(){ cin>>nv>>ne; for(int i=0;i<ne;++i){ int a,b,d; scanf("%d%d%d",&a,&b,&d); node temp; temp.v=b; temp.w=d; graph[a].push_back(temp); temp.v=a; graph[b].push_back(temp); } int k; cin>>k; for(int i=0;i<k;++i){ check.clear(); check.resize(nv); for(int j=0;j<nv;++j){ scanf("%d",&check[j]); } flag=false; p=0; flag=dijkstra2(check[0]); if(flag)cout<<"Yes"<<endl; else{ cout<<"No"<<endl; } } return 0; }