1. 程式人生 > >記 2018.9.8 PAT甲級&題解

記 2018.9.8 PAT甲級&題解

寫在前面

前兩天考完就想寫了,結果一直拖到現在orz……8月中旬的時候無意中看到PAT這個東東,因為剛好在準備保研,要複習機試的東西,就報了這個,雖然之前有接觸過一點點ACM,不過個人對這種資料結構演算法一直都不是特別擅長,準備了半個多月,每天都在刷題總結複習中度過,直到考完才感覺鬆了一口氣,放一下分數和排名吧=w=(雖然感覺可以考的更好,不過也還算滿意啦)
分數:91/100
排名:78/2237

感受

這次PAT考試有幾個特點:

  1. 放寬了時間限制,也就是說完全暴力也可以AC……
  2. 第一道題邏輯難,據說是頂級25分題?太打擊了,反正我一開始就沒思路(當時以為不能暴力…)
  3. STL、DFS太重要了……
      考試一共是3個小時,考前幾次模擬我都是第一道題15min左右,第二、三道30min左右,最後一道視情況(30min-1h),不過這次考試顯然有點特殊,第一道狼人殺就把我打擊到了,10幾分鐘都沒有思路,只能先放著,跳到第二道,二、三都不是很難,1h左右跑通兩道,提交的時候有一道錯了一個3分的測試點,沒管,直接看最後一道= =(考完發現那個錯誤其實很低階。。)
      最後一道是LCA,考試前做了一道LCA的,是針對BST的,BST的LCA很容易找,但是考試要求求的是普通二叉樹的LCA,一開始一直想的是各種先後序層序遍歷序列找,試了快一個小時都沒成功,最後換成DFS,10minAC……
      做完三道只剩半個小時了,回去看那道狼人殺,試了10min連樣例都跑不通QAQ內心一直想放棄,突然靈光一現(?)改了一種半暴力的方法,居然跑通樣例了,這時只剩5min了,趕緊提交,居然只錯了一個測試點,不過剩下的時間也不夠了,就這樣結束了我的第一次(也是最後一次)PAT考試@
    [email protected]

    ##一些建議
  4. 考綱裡的每個點都要掌握!資料結構主要是佇列、棧、連結串列、樹、圖,演算法主要是最短路、DFS、BFS那些
  5. 考前一個月每天都要保持題量和題感,最好是把題庫裡的都做一遍!
  6. 每次遇到不會的題不要一下子就去網上找題解,一般2h想不出的我才會去看看別人的思路,然後看看自己是哪裡想錯了,進行改進,不要直接copy程式碼!
  7. 確定考場後要第一時間確定考場提供的IDE是哪些,確保有自己熟悉的IDE,沒有的話最好提前一個月更換IDE進行練習(比如我之前一直是用C-Free的,郵件問了考場老師才知道考場沒有C-Free,只有Dev-C++…),不然就會像考場裡很多同學一樣,花了不少時間在熟悉IDE上……

題解

說了這麼多,放一下本次考試題解吧(對應PAT題庫1148-1151),均是可以AC的

  1. 第一題狼人殺,題意就是給出N個人的敘述,N個人中有兩個狼人(1個撒謊1個不撒謊),而所有人中撒謊的只有兩個,也就是說最終有一個撒謊的狼人和一個撒謊的村民,因此可以直接暴力列舉所有狼人組合,對每一個狼人組合,統計撒謊的狼人數和撒謊的村民數,如果都為1說明找到答案,如果列舉所有組合後都找不到答案,說明無解。
#include <iostream>
#include <algorithm>

using namespace std;

int main(){
	int N;
	cin>>N;
	int arr[N+1];
	for(int i=1;i<=N;i++) cin>>arr[i];
	bool flag=false;
	int a,b;
	// 列舉每一種狼人組合
	for(int i=1;i<=N;i++){
		for(int j=i+1;j<=N;j++){
			int lie_wolf=0,lie_human=0;
			for(int k=1;k<=N;k++){// 判斷該狼人組合下是否滿足1個撒謊的狼人+1個撒謊的村民
				if(k==i || k==j){// 狼人
					if(arr[k]>0 && arr[k]==i || arr[k]==j) lie_wolf++;
					else if(arr[k]<0 && abs(arr[k])!=i && abs(arr[k])!=j) lie_wolf++;
				}else{// 村民
					if(arr[k]>0 && arr[k]==i || arr[k]==j) lie_human++;
					else if(arr[k]<0 && abs(arr[k])!=i && abs(arr[k])!=j) lie_human++;
				}
			}
			if(lie_wolf==1 && lie_human==1){
				a=i;
				b=j;
				flag=true;
				break;
			}
		}
		if(flag) break;
	}
	if(flag) cout<<a<<" "<<b<<endl;
	else cout<<"No Solution"<<endl;
	return 0;
}

2.第二題題意是給出一些危險物配對,比如A和B不能一起出現,B和C不能一起出現(但A和C可以一起出現,所以不是並查集問題),求所給序列中有沒有危險物。思路也很簡單,直接暴力遍歷序列,找有沒有危險匹配即可。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int MAXV=100001;
vector<int> m[MAXV];// 儲存每個物品對應的危險物品列表

int main(){
	int N,M;
	cin>>N>>M;
	for(int i=0;i<N;i++){
		int a,b;
		cin>>a>>b;
		m[a].push_back(b);
		m[b].push_back(a);
	}
	for(int i=0;i<M;i++){
		int K;
		cin>>K;
		int arr[K];
		bool flag=true;
		for(int j=0;j<K;j++) cin>>arr[j];
		for(int j=0;j<K-1;j++){// 從前到後暴力比較
			for(int k=j+1;k<K;k++){
				if(find(m[arr[j]].begin(),m[arr[j]].end(),arr[k])!=m[arr[j]].end()){
					flag=false;
					break;
				}
			}
			if(!flag)break;
		}
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}

3.**第三題是售貨商問題。**不過這道題不需要去求解,只需要判斷所給序列是不是滿足條件即可,思路也很簡單,先判斷路徑是否連通,不連通就輸出“Not a TS cycle”,連通的話再判斷序列是否包含了全部結點且首尾結點相同,是則為TS cycle或TS simple cycle,二者可以通過序列長度進行判斷。

#include <iostream>
#include <algorithm>
#include <set>

using namespace std;

const int INF=0x3fffffff;
const int MAXV=201;
int G[MAXV][MAXV];

int main(){
	int N,M,K;
	cin>>N>>M;
	fill(G[0],G[0]+MAXV*MAXV,-1);
	for(int i=0;i<M;i++){
		int a,b,dis;
		cin>>a>>b>>dis;
		G[a][b]=G[b][a]=dis;
	}
	cin>>K;
	int ans_index,ans_len=INF;
	for(int i=1;i<=K;i++){
		int n;
		cin>>n;
		int path[n],len=0;
		bool flag=true;
		set<int> s;
		for(int j=0;j<n;j++){
			cin>>path[j];
			s.insert(path[j]);
		}
		for(int j=0;j<n-1;j++){
			if(G[path[j]][path[j+1]]==-1){
				flag=false;// 說明所給路徑不連通
				break;
			}else len+=G[path[j]][path[j+1]];// 路徑總長度
		}
		if(flag){
			if(s.size()!=N || path[0]!=path[n-1]){
				printf("Path %d: %d (Not a TS cycle)\n",i,len);
			}else{
				if(len<ans_len){// TS cycle 記錄最短路徑長度及路徑編號
					ans_len=len;
					ans_index=i;
				}
				if(s.size()==n-1) printf("Path %d: %d (TS simple cycle)\n",i,len);
				else printf("Path %d: %d (TS cycle)\n",i,len);
			}
		}
		else printf("Path %d: NA (Not a TS cycle)\n",i);
	}
	printf("Shortest Dist(%d) = %d",ans_index,ans_len);
	return 0;
}

4.最後一題是LCA問題。要求找二叉樹中任兩個結點的最小公共祖先結點。我的思路是先建樹,然後對兩個結點進行dfs,求出根節點到這兩個結點的路徑,對兩條路徑從頭到尾比較,出現的第一個不同的結點則退出迴圈,該結點的前一個結點就是它們的LCA(比如:3結點的路徑是1->5->3,4結點的路徑是1->5->4,則它們的LCA為5),如果沒有出現不同的結點說明二者是包含關係,根據兩條路徑長度可以判斷誰是祖先。

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

using namespace std;

const int MAXV=10001;

struct node{
	node* lchild;
	node* rchild;
	int data;
	node(){
		lchild=rchild=NULL;
	}
};

int in[MAXV],pre[MAXV];
map<int,int> m;
node* create(int preL,int preR,int inL,int inR){
	if(preL>preR) return NULL;
	node* root=new node;
	root->data=pre[preL];
	int i;
	for(i=inL;i<=inR;i++){
		if(in[i]==pre[preL]) break;
	}
	int len=i-inL;
	root->lchild=create(preL+1,preL+len,inL,i-1);
	root->rchild=create(preL+len+1,preR,i+1,inR);
	return root;
}

vector<int> path,ans;
bool flag=false;
void dfs(node* root,int v){
	if(root==NULL) return;
	if(root->data==v){
		flag=true;
		path.push_back(root->data);
		ans=path;
		path.pop_back();
		return;
	}else{
		path.push_back(root->data);
		dfs(root->lchild,v);
		if(flag) return;
		path.pop_back();
		path.push_back(root->data);
		dfs(root->rchild,v);
		if(flag) return;
		path.pop_back();
	}
}

int main(){
	int M,N;
	cin>>M>>N;
	for(int i=0;i<N;i++){
		cin>>in[i];
		m[in[i]]=i;// 記錄某個結點是否出現過
	}
	for(int i=0;i<N;i++) cin>>pre[i];
	node* root=create(0,N-1,0,N-1);// 根據先序中序序列建樹
	for(int i=0;i<M;i++){
		int u,v;
		cin>>u>>v;
		if(m.count(u)==0 && m.count(v)==0) printf("ERROR: %d and %d are not found.\n",u,v);
		else if(m.count(u)==0) printf("ERROR: %d is not found.\n",u);
		else if(m.count(v)==0) printf("ERROR: %d is not found.\n",v);
		else{
			// dfs分別遍歷u,v結點,得到兩條路徑
			vector<int> pu,pv;
			path.clear();
			flag=false;
			dfs(root,u);
			pu=ans;
			path.clear();
			flag=false;
			dfs(root,v);
			pv=ans;
			// 找兩條路徑第一個不同的結點
			int j;
			for(j=0;j<min(pu.size(),pv.size());j++){
				if(pu[j]!=pv[j]) break;
			}
			if(j!=min(pu.size(),pv.size())) printf("LCA of %d and %d is %d.\n",u,v,pu[j-1]);
			else if(pu.size()<pv.size()) printf("%d is an ancestor of %d.\n",u,v);
			else printf("%d is an ancestor of %d.\n",v,u);
		}
	}
	return 0;
}

最後

相關推薦

2018.9.8 PAT甲級&題解

寫在前面 前兩天考完就想寫了,結果一直拖到現在orz……8月中旬的時候無意中看到PAT這個東東,因為剛好在準備保研,要複習機試的東西,就報了這個,雖然之前有接觸過一點點ACM,不過個人對這種資料結構演算法一直都不是特別擅長,準備了半個多月,每天都在刷題總結複習中

20189PAT甲級考試(北京工業大學考場)

這次第一題就給人很意外,是個提交正確率和最後一題正確率一樣低的題,不像以前一樣水了。我吭哧吭哧做了半個多小時,才發現題讀錯了,撲街,第一次放棄。 接著做第二題,像是道並查集,但是並查集我很久沒寫了,忘了怎麼寫了,不會了,就用了個set模擬,但是STL庫我又忘了

之A Fresh Start(2018/9/2-2018/9/8

自己 計算 三分 專業課 探索 可見 不出 技術 學習過程 新學期、新開始、新面貌、新姿態、新目標、新動力……希望自己不忘初心,在自己的地圖上摸索自己的路,然後一直走下去,永不回頭。在此平臺立下一個flag:至少每周一記,包括本周內所做所想所感所悟,繼而更加堅定以後的征程,

2018年12月9PAT甲級考試總結

從九月初考完乙級之後,至今一直在準備甲級考試。 主要目的是想有這麼一個成績,可以代表自己的程式設計水平,一方面激勵自己繼續學習,另一方面也有利於找找實習。 其實對成績的期待也不是很高,有個五六十也就不錯了,因為之前九月份考試認識一個計算機專業考甲級的女生,她也就是考了五十幾分。另外能考個五六

2018.9.8信息奧賽集訓評測報告總結

分號 飛揚 成績 基本 算法 可能 要求 中間 兩個 9.8信息奧賽集訓評測報告總結 一、重定向寫錯:   a.文件名拼寫錯誤,如:徐飛揚   b.缺逗號,如:高湛東   c.三個參數沒寫對,如張柏榮,趙芯蕊,寫了兩個r   d.輸入輸出文件沒按要求寫,如王嘉偉寫的beei

2018-2019賽季多校聯合新生訓練賽第三場(2018/12/8)補題題解

感慨 得複習回溯和dfs了。。。 A 變形蟲(語法基礎) 程式碼 #include <bits/stdc++.h> using namespace std; map<int,int> num; int main() { ios::sync_with_stdio(0);

FZSZ 2018.9.8.?校聯考

關於第2題的想法: 因為一定要保含某個標記(節點),所以可以從這個點為根節點出發找最長鏈。但是這樣,由於詢問(求某個標記為根的最長鏈長度)比較多,如果用普通求最長鏈的話,還要每次都DFS一遍,這樣是非常不划算的,因為這樣重複獲得了一些已經獲得的結果。 於

PAT甲級題解】1020 Tree Traversals

程式碼如下: #include <iostream> #include <stack> #include <queue> #include <vector> using namespace std; struct Tree

PAT甲級題解目錄

ID Title C/C++ 備註 1001 A+B Format (20) 檢視題解 字串處理 1002 A+B for Polynomials (25) 檢視題解 模擬 1

2018.3.18 PAT甲級比賽

寫個部落格,紀念一下今天的比賽吧。。。 A題 1140. Look-and-say Sequence (20) 時間限制 400 ms 記憶體限制 65536 kB

PAT甲級題解記錄

個人部落格:楓之羽 題目 題解連結 備註 1001 A+B Format (20) 題解 string流 1002 A+B for Polynomials (25)

2018.9.8面試,上海仰空網路科技

地點:光明路浦江大廈 要996,沒有去, 人事說話很溫柔。 面試題 █ .基礎知識 1.啟動一個執行緒是用run()還是start()? 2。談談你對ThreadLocal的使用,在什麼情況下使用? 3。談談你對資料庫事務的理解,spring事務的

PAT甲級】1148——1151 9.8秋季考試

考試之前想先耍點小聰明,一直沒點開始 先把我的堆優化dj演算法敲好了再點開始。 結果點開始之後時間還是給我扣了3分鐘。。。醉了醉了 本以為一個小時就能敲好的,結果花了一個小時半,正確率也挺低的。。。 兩次段錯誤,沒看清資料範圍,加一次沒用map,用陣列來

2018/6/4~2018/6/8

als val lap 如果 每一個 信息 pset 調整 IE 一轉眼一周時間已經過去,這一周的任務是做一個實時更新的窗體運用,項目的要求有如下三點: 1、界面上窗口號不能寫死,要可配置的。 2、設置一個定時器,每隔10秒更新數據。 3、由於有五個窗口,所以要使用五個Da

我的暑假周2018.8.19

黑馬 現在 效率 重要 視頻 我們 學習效率 就是 難受 這一周有一天是情人節,就在情人節這天,我們導員溫導來我家家訪了,還買了點禮品,真是不好意思,在我家和我還有我爸聊了會天,把我在學校的情況說了說,跟我說大學要有目標,大學的學業還是很重要的。也不知道為啥,就是感覺溫導好

庫裡32+9+8刷五三分 勇士輕取雷霆迎開門紅

阿里巴巴官方釋出微博稱,連續幾日,一篇名為《阿里員工透露:馬總早移走 1200 億人民幣!網友:不愧是老師》的文章被有組織的進行惡意傳播。阿里巴巴官方釋出微博稱,連續幾日,一篇名為《阿里員工透露:馬總早移走 1200 億人民幣!網友:不愧是老師》的文章被有組織的進行惡意傳播。 對此,阿里表示,該文完全捏造事

2018.9.16 第一次參加csp認證考試

9.16的csp認證= =時間卡的挺好,剛好在數模國賽的關鍵期間。 但是還是得去,畢竟錢都交了…… 頭天晚上熬夜把數模大部分做了出來,快7點了回寢室睡了一會,11點起來點外賣吃了就走了……12點30+到了考場,1點的時候開始問周圍人為什麼還不開始,然後得知開始時間是1點3

2018pat甲級冬季考試總結

 今天上午12點半吃完飯後發現還有一個小時才考試,於是找了個教室睡了一覺,起來發現已經1點20了,於是馬不停蹄的跑去考場,拿出身份證和准考證後慌忙的找到位置,然後夢夢悠悠的就點開了考試。。 第一題看了一遍,發現就看懂一個超越數還是中文的。瞅了有五分鐘,還是沒看懂,旁邊兩個人卻已經開始敲

第一次參加PAT(附18.12.09PAT乙級題解

寫在前面: 18年12月09日 第一次參加PAT乙級,在停止提交的那一刻,我的心裡只有倆個字:遺憾。這次乙級的後倆題是甲級的前倆題一模一樣,不過甲級題是英文。並不是輸在了題目有多難,以我這個菜雞的水平,這套乙級題應該至少能考85+的。可是由於我時間分配的不合理,導致了這次考試的失敗。真是芝麻沒撿到還弄丟了個

PAT甲級真題題解(更新中)

2018年11月17日 13:27:17 Czq6666 閱讀數:9 標籤: pat甲級 資料結構