杭電計算機17年複試真題詳解

目錄

文章目錄


左側有杭電覆試專欄,有需求的小夥伴可以進去查看我對歷年真題的一些做法以及我複試的一些日記。

以上也算是爲後來人做的一點貢獻吧~
#題目一
關羽過關斬三將,輸入四個人的武力值(大於0小於50),若超過界限需要重新輸入,關羽的武力值x,將士武力值爲y,滿足(x-y)^2+(x-y)+41 若爲素數則關羽獲勝,若關羽三次獲勝輸出WIN,若失敗則輸出失敗的將領序號(第幾關)。
思路:

  1. 首先完成素數打表模塊兒,這個素數表在一會兒進行判斷的時候使用
  2. 完成判斷模塊兒,判斷關羽能不能贏。
  3. 格式化輸入模塊兒,輸入不合法,就判定讓其繼續進行輸入。
  4. 主程序進行武力值的遍歷,每次遍歷都判斷其合法性,不合法就跳出,並顯示是在哪一關開始不合法的
#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAX 10000
using namespace std;

bool prime[MAX];
void is_prime(){
	memset(prime,true,MAX);
	for(int i=2;i<MAX;i++){
		if(prime[i]){
			for(int j=2*i;j<MAX;j+=i)
				prime[j]=false;
		}		
	}
	prime[0]=false;prime[1]=false;
}
bool solve(int x,int y){
	int temp=(x-y)*(x-y)+(x-y)+41;
	if(prime[temp])//如果公式的計算結果是素數,那麼就是關於贏了 
		return true;
	else
		return false;
}
int main(){
	int enemy[4],x,i;
	is_prime();//進行預處理操作, 
	while(true){
		bool flag=true;//標記輸入是否合法 
		scanf("%d",&x);
		if(x<=0||x>=50)
			flag=false; 
		for(i=1;i<4;i++){
			scanf("%d",&enemy[i]);
			if(enemy[i]<=0||enemy[i]>=50)
				flag=false; 
		}
		if(flag)
			break;
		else{
			printf("武力值應該在0到50之間\n");
			continue;
		}
	}
	bool flag=true;//如果輸一把立即將此標記爲false; 
	for(i=1;i<4;i++){
		if(!solve(x,enemy[i])){
			flag=false;
			break;
		}	
	}
	if(flag){
		printf("WIN\n");
	}
	else
		printf("關羽輸給了第%d個將軍",i);
	return 0;
}

不保證答案正確性,只是提供一種思路
#題目二:
輸入N個員工,每個員工輸出ID號,上班時間,下班時間,第一行輸出最早去的員工的ID和上班時間第二行輸出最遲走的員工的ID和下班時間第三行輸出工作最久的員工的ID和上班時間(數據瞎編的)
sampleinput:
ID100001,07:00:0017:00:00
ID100002,08:00:0018:00:00
ID100003,09:00:0021:00:00
sampleout:
OPEN:ID100001,07:00:00
CLOSE:ID100003,21:00:00
(…):ID100003,12:00:00
思路:
1.定義時間結構體,方便存儲時間類型的數據
2.定義學生結構體,存儲學生的相關信息,信息裏面包含時間結構體
3.根據題目要求定義三種排序規則cmp1,cmp2,cmp3.然後調用這些排序函數,逐行輸出排序之後的結果即可。

#include<stdio.h>
#include<string.h>
#include<time.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct time{
	int hour;
	int min;
	int sec;	
};
struct employer{
	char id[100];
	struct time t1,t2;
	int diff;
}buf[100];
bool cmp1(employer a,employer b){//比較出上班時間最早的 
	if(a.t1.hour!=b.t1.hour)
		return a.t1.hour<b.t1.hour;
	else if(a.t1.min!=b.t1.min)
		return a.t1.min<b.t1.min;
	else
		return a.t1.sec<b.t1.sec;
}
bool cmp2(employer a,employer b){//比較出下班時間最晚的 
	if(a.t2.hour!=b.t2.hour)
		return a.t2.hour>b.t2.hour;
	else if(a.t2.min!=b.t2.min)
		return a.t2.min>b.t2.min;
	else
		return a.t2.sec>b.t2.sec;
}
bool cmp3(employer a,employer b){//比較出留在單位的時間最長的 
	return a.diff>b.diff; 
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%s%d:%d:%d %d:%d:%d",&buf[i].id,&buf[i].t1.hour,&buf[i].t1.min,&buf[i].t1.sec,
		&buf[i].t2.hour,&buf[i].t2.min,&buf[i].t2.sec);
		buf[i].diff=(buf[i].t1.hour*3600+buf[i].t1.min*60+buf[i].t1.sec)-(buf[i].t2.hour*3600+buf[i].t2.min*60+buf[i].t2.sec);	
	}
	//每進行一次比較,就輸出一次排序後的結果
	sort(buf,buf+n,cmp1);
	printf("%s %d:%d:%d\n",buf[0].id,buf[0].t1.hour,buf[0].t1.min,buf[0].t1.sec);
	sort(buf,buf+n,cmp2);
	printf("%s %d:%d:%d\n",buf[0].id,buf[0].t2.hour,buf[0].t2.min,buf[0].t2.sec);
	sort(buf,buf+n,cmp3);
	printf("%s %d:%d:%d\n",buf[0].id,buf[0].t1.hour,buf[0].t1.min,buf[0].t1.sec);
	return 0;
}

#題目三:
有一個MN的材料和一個st的模板,從材料中切除模板,求最大能切出來的模板的數量。
sample input

3 4
a b c d
c d a b
a c c d
2 2
a b
c d
sample out
2
sample output

思路:

  1. 定義兩個字符數組將這兩幅圖存儲起來
  2. 使用一個判斷模塊兒,當進行搜索的時候,判斷該位置是否合法(也就是以該位置爲起點的ST圖形是否能和輸入的ST圖形恰好匹配)
  3. 構造一個初始化模塊兒,當位置合法的時候,可以選擇使用或者不使用這種位置
  4. 使用深搜模塊兒,逐行進行掃描。
    1. 如果到某一位置,判斷時合法。我們採取兩種行動(要麼將大圖中匹配的位置標記爲0,然後繼續深度搜索,要麼就當什麼事都沒有發生,繼續逐行掃描)採取這兩種操作的原因是,我們不知道哪種操作是更好的結果,所以我們就都試試
    2. 當該行掃描完之後,進入下一行繼續進行掃描。
    3. 程序出口是掃描到了最後一行
    4. 因爲遞歸過程中遍歷了所有的可能,如果遇到更優解,我們需要進行答案的更新。

寫法一:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define MX 100
#define MY 100
char map_a[MX][MY];//存儲大圖
char map_b[MX][MY];//存儲小圖
//char temp[MX][MY];//存儲變化中的圖 
using namespace std;
int m,n,s,t,ans;//用來儲存大圖和小圖的長和寬 
bool judge(char Map[MX][MY],int x,int y){//判斷大圖裏面是否包含小圖 
	for(int i=0;i<s;i++){
		for(int j=0;j<t;j++)
			if(Map[x+i][y+j]!=map_b[i][j])
				return false;
	} 
	return true;
}
void dfs(char Map[MX][MY],int x,int y,int max){
	if(max>ans)//更新答案 
		ans=max;
	if(y>=n)//給出程序出口 
		return ;
	if(x>=m)
		dfs(Map,0,y+1,max);//第一列走完了之後,換第二列 
	else{
		if(judge(Map,x,y)){
			char temp[MX][MY]={0};
			for(int i=0;i<m;i++)//初始化中間圖 
				for(int j=0;j<n;j++)
					temp[i][j]=Map[i][j];
			for(int i=0;i<s;i++)
				for(int j=0;j<t;j++)
					temp[x+i][y+j]='0';//把參與過匹配的地方標記爲0 
			dfs(temp,x+s,y,max+1);//確定取這一塊兒 
			dfs(Map,x+1,y,max);//不取這一塊兒,按部就班繼續走 
		}
		else
			dfs(Map,x+1,y,max);//不匹配則按列走 		
	} 

}
int main(){
	cin>>m>>n;//輸入大圖的長和寬 
	for(int i=0;i<m;i++)
		for(int j=0;j<n;j++)
			cin>>map_a[i][j]; 
	cin>>s>>t;//輸入小圖的長和寬 
	for(int i=0;i<s;i++)
		for(int j=0;j<t;j++)
			cin>>map_b[i][j];
	ans=0;
	dfs(map_a,0,0,0); 
	cout<<ans<<endl;	
	return 0;
} 

寫法二:
此寫法更新於0324杭電6教計算機考研教室

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std; 
#define MAX 1010
char map[MAX][MAX],mapb[MAX][MAX];
char temp[MAX][MAX];//記錄中間圖的變換,方便在遞歸中的回溯進行使用 
int M,N,s,t;//分別爲這兩個圖形的長和寬 
int Max,ans;//分別記錄每次遍歷的最大塊兒數和最終答案 
bool judge(char map[][MAX],int i,int j){//傳入當前所搜索到的位置 
	int x=i;int y=j;//x來表示行數,y來表示列數 
	for(i=0;i<s;i++)//判斷兩個圖是否匹配 
		for(j=0;j<t;j++)
			if(map[x+i][y+j]!=mapb[i][j])
				return false;
	return true;
}
init_temp(int x,int y){//將已經遍歷過的位置標記 
	for(int i=0;i<M;i++) 
		for(int j=0;j<N;j++)
			temp[i][j]=map[i][j];
	for(int i=0;i<s;i++)
		for(int j=0;j<t;j++)
			temp[x+i][y+j]='0'; 
}
void dfs(char map[][MAX],int x,int y,int Max){
	if(ans<Max)//ans來記錄塊兒的數量 
		ans=Max;
	if(x>=M){//記錄遞歸出口,走到最後一行就返回 
		return ;
	}
	for(int i=y;i<N;i++){//對x行的每一列都進行搜索
		 if(judge(map,x,i)){//滿足判段進行下一步遞歸 
		 	init_temp(x,i);
			dfs(temp,x,i+t,Max+1);//將遍歷過的位置標記,然後繼續遍歷	
		 }	 
	} 
	dfs(map,x+1,0,Max);
}
int main(){
	cin>>M>>N;
	for(int i=0;i<M;i++)	
		for(int j=0;j<N;j++)
			cin>>map[i][j];
	cin>>s>>t;
	for(int i=0;i<s;i++)
		for(int j=0;j<t;j++)
			cin>>mapb[i][j];
	ans=0;Max=0;
	dfs(map,0,0,0);	
	cout<<ans<<endl;
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章