PAT (Advanced Level) Practice 题解代码 - I (1001-1050)

PAT

PAT (Advanced Level) Practice - I(1001-1050)

--------------------------------------------------------------------------------

1001-1167(已更新至最新!)

1001-1050

链接:https://pan.baidu.com/s/1Z4y8nR2VdgL9KWUQxwbKOA
提取码:9cv4
--------------------------------------------------------------------------------

更多详见>>

OJ题解系列 目录导航帖
--------------------------------------------------------------------------------

题目传送门

PAT (Advanced Level) Practice
--------------------------------------------------------------------------------

这里是PAT (Advanced Level) Practice - I(1001-1050)
这是一个全新的起点,我们完成了乙级考试的小目标,向着甲级考试的大目标前进,你将会看到一片新的世界,在数据结构和算法的大海里遨游
首先,我们讲讲两种考试的区别:
1.题面描述不同,乙级考试采用中文描述,甲级考试采用英文描述
2.题目数量不同,乙级考试是5道题,甲级考试是4道题
3.题目的分值不同,乙级考试的分值分布为15/20/20/20/25,甲级考试的分值分布为20/25/25/30
4.难度不同,甲级考试相对乙级考试来说会增加一个难度级别,主要体现在对数据结构的掌握上,如树和图——主要有BST/BBST/CBT/Heap/DAG,算法方面在原有的难度基础之上加深一点(比方说大模拟),引入了一些简单DP
知己知彼方能百战不殆,我们了解基本的区别之后,大家也不用太担心考试的难度问题,毕竟数据规模n不像竞赛要求那么高,很多算法用最普通的枚举方法往往也能取得满分!

接下来就是题解部分了,每道算法题都标注有对应的算法标签,对于那些易错、较难或是测试点比较特殊的题目会着重标注,本章推荐的题目有:

1003 Emergency (25 分)图论 + Dijkstra
1018 Public Bike Management (30 分)
1030 Travel Plan (30 分)
图论 + Dijkstra + DFS
1010 Radix (25 分)数论 + 进制 + 二分
1049 Counting Ones (30 分)数论
1014 Waiting in Line (30 分)
1017 Queueing at Bank (25 分)
1026 Table Tennis (30 分)
大模拟
1021 Deepest Root (25 分)树,二叉树
1033 To Fill or Not to Fill (25 分)
1034 Head of a Gang (30 分)
贪心

--------------------------------------------------------------------------------

1001 A+B Format (20 分)

算法标签: 模拟
注意点: 以3位为一个单位对数字进行划分,输出时要输出%03d

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	int c = a+b;
	if(c<0){
		cout << "-";
	}
	c = abs(c);
	if(c < 1000){
		cout << c % 1000 << endl;
	}else if(c<1000000){
		cout << c/1000 << ",";
		printf("%03d\n",c%1000);
	}else{
		cout << c/1000000 << ",";
		printf("%03d,%03d\n",c/1000%1000,c%1000);
	}
	
	return 0;
} 

1002 A+B for Polynomials (25 分)

算法标签: 模拟 + 高精
注意点: 多项式加法,本质上和高精度加法一样,都是开一个比较大的数组,然后从尾到头依次累加,注意多项式加法不需要处理进位的问题

#include<bits/stdc++.h>
using namespace std;
double a[1005];
double b[1005];
double c[1005];
int main(){
	int K;
	int emax = -1;
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	
	scanf("%d",&K);
	for(int i=1;i<=K;i++){
		int e;
		double coeff;
		scanf("%d%lf",&e,&coeff);
		emax = max(emax,e);
		a[e] = coeff;
	}
	
	scanf("%d",&K);
	for(int i=1;i<=K;i++){
		int e;
		double coeff;
		scanf("%d%lf",&e,&coeff);
		emax = max(emax,e); 
		b[e] = coeff;
	}
	
	for(int i=emax;i>=0;i--){
		c[i] = b[i] + a[i];
	}
	
	int cnt = 0;
	for(int i=emax;i>=0;i--){
		if(c[i]!=0){
			cnt++;
		}
	}
	
	cout << cnt;
	for(int i=emax;i>=0;i--){
		if(c[i]!=0){
			printf(" ");
			printf("%d %.1lf",i,c[i]);
		}
	}
	
	return 0;
} 

1003 Emergency (25 分)

算法标签: 图论 + Dijkstra
注意点: Dijkstra算法经典题,本题不用堆优化, O ( n 2 ) O(n^2) O(n2)复杂度也能满分
本题考察的重点是最短路的松弛过程中,可直接更新最短路的数量,因为更新距离的过程就是更新数量的过程,两者算法在本质上是一样的(此处重点理解)

#include<bits/stdc++.h>
using namespace std;
int N,M,C1,C2;
int a[505];
int w[505];
int dp[505];
bool vis[505];
int num[505];

struct node{
	int to;
	int dis;
};
vector<node> G[505];

int maxdis = -1;

void Dijstra(int s){
	memset(dp,0x3f,sizeof(dp));
	dp[s] = 0;
	w[s] = a[s];
	num[s] = 1;
	
	for(int i=0;i<N;i++){
		int u = -1;
		int minnum = INT_MAX;
		for(int j=0;j<N;j++){
			if(!vis[j] && dp[j]<minnum){
				minnum = dp[j];
				u = j;
			}
		}
		if(u==-1){
			return;
		}
		vis[u] = true;
		for(int j=0;j<G[u].size();j++){
			int v = G[u][j].to;
			int dis = G[u][j].dis;
			if(!vis[v]){
				if(dp[u]+dis<dp[v]){
					dp[v] = dp[u] + dis;
					w[v] = w[u] + a[v];
					num[v] = num[u];
				}else if(dp[u]+dis==dp[v]){
					if(w[v]<w[u]+a[v]){
						w[v] = w[u] + a[v];
					}
					num[v] += num[u];
				}	
			}
		}	
	}
	
}
int main(){
	cin >> N >> M >> C1 >> C2;
	for(int i=0;i<N;i++){
		cin >> a[i];
	} 
	for(int i=0;i<M;i++){
		int c1,c2,L;
		cin >> c1 >> c2 >> L;
		node temp;
		temp.dis = L;
		temp.to = c2;
		G[c1].push_back(temp);
		temp.to = c1;
		G[c2].push_back(temp);
	}
	Dijstra(C1);
	printf("%d %d\n",num[C2],w[C2]);
	 
	return 0;
} 

1004 Counting Leaves (30 分)

算法标签: 树,二叉树 + DFS
注意点: DFS遍历整棵树,DFS的深度depth就是树的层次,统计每个层次的叶结点数量,最后输出结果

#include<bits/stdc++.h>
using namespace std;

int N,M;
int a[105];
vector<int> child[105];
int maxdepth = -1;

void dfs(int depth,int root){
	if(child[root].size()==0){
		a[depth]++;
	}
	if(depth>maxdepth){
		maxdepth = depth;
	}	
	for(int i=0;i<child[root].size();i++){
		dfs(depth+1,child[root][i]);
	}
}

int main(){
	memset(a,0,sizeof(a));
	cin >> N >> M;
	for(int i=0;i<M;i++){
		int id;
		cin >> id;
		int k;
		cin >> k;
		for(int j=0;j<k;j++){
			int t;
			cin >> t;
			child[id].push_back(t);
		}
	}	
	dfs(1,1);
	
	
	for(int i=1;i<=maxdepth;i++){
		if(i!=1){
			printf(" %d",a[i]);
		}else{
			printf("%d",a[i]);
		}
	}

	return 0;
}

1005 Spell It Right (20 分)

算法标签: 模拟 + 字符串

#include<bits/stdc++.h>
using namespace std;

int main(){
	string s;
	cin >> s;
	int total = 0;
	for(int i=0;i<s.size();i++){
		total += s[i] - '0';
	} 
	int a[3];
	bool flag = false;
	a[0] = total / 100;
	a[1] = total / 10 % 10;
	a[2] = total % 10;
	if(a[0]==0 && a[1]!=0){
		a[0] = -1;
	}else if(a[0]==0 && a[1]==0){
		a[0] = -1;
		a[1] = -1;
	}
	for(int i=0;i<3;i++){
		switch(a[i]){
			case 0:cout << "zero";break;
			case 1:cout << "one";break; 
			case 2:cout << "two";break;
			case 3:cout <<"three";break;
			case 4:cout <<"four";break;
			case 5:cout <<"five";break;
			case 6:cout <<"six";break;
			case 7:cout <<"seven";break;
			case 8:cout <<"eight";break;
			case 9:cout <<"nine";break;
			default:break;
		}
		if(i==2){
			
		}else{
			if(a[i]==-1){
				
			}else{
				cout <<" ";
			}
		}
	}
	
	return 0;
}

1006 Sign In and Sign Out (25 分)

算法标签: 模拟 + 排序
注意点: 根据时间的变化情况确定是入库还是出库操作,注意满足题意的要求必须是当天进出各一次才算,单入库或者单出库都不在统计的范围内

#include<bits/stdc++.h>
using namespace std;
int Great(int h1,int m1,int s1,int h2,int m2,int s2){
	if(h1!=h2){
		return h1>h2;
	}else if(m1!=m2){
		return m1>m2;
	}else if(s1!=s2){
		return s1>s2;
	}
}
int main(){
	int M;
	cin >> M;
	int ans_h = 24, ans_m = 0, ans_s = 0;
	int end_h = 0, end_m = 0, end_s = 0;
	string s1,s2;
	for(int i=0;i<M;i++){
		string s;
		cin >> s;
		int s_h,s_m,s_s;
		int e_h,e_m,e_s;
		scanf("%d:%d:%d",&s_h,&s_m,&s_s);
		scanf("%d:%d:%d",&e_h,&e_m,&e_s);
		if(Great(ans_h,ans_m,ans_s,s_h,s_m,s_s)){
			ans_h = s_h;
			ans_m = s_m;
			ans_s = s_s;
			s1 = s;	
		}
		if(Great(e_h,e_m,e_s,end_h,end_m,end_s)){
			end_h = e_h;
			end_m = e_m;
			end_s = e_s;
			s2 = s;
		} 
	}
	cout << s1 << " " << s2 << endl;
	return 0;
}

1007 Maximum Subsequence Sum (25 分)

算法标签: 动态规划
注意点: DP状态转移方程为: d p [ i ] = m a x ( d p [ i − 1 ] + a [ i ] , a [ i ] ) dp[i]=max(dp[i-1]+a[i],a[i]) dp[i]=max(dp[i1]+a[i],a[i])

#include<bits/stdc++.h>
using namespace std;
int a[10005];
int dp[10005];
int site[10005];
int main(){
	int K;
	scanf("%d",&K);
	bool f = false;
	for(int i=0;i<K;i++){
		scanf("%d",&a[i]);
		if(a[i]>=0){
			f = true;
		}
	}
	dp[0] = a[0];
	if(!f){
		printf("0 %d %d\n",a[0],a[K-1]);
		return 0;
	}
	for(int i=1;i<K;i++){
		if(a[i]<dp[i-1]+a[i]){
			dp[i] = dp[i-1]+a[i];
			site[i] = site[i-1];
		}else{
			site[i] = i;
			dp[i] = a[i];
		}
	}
	int t;
	int maxnum = -0x7f7f7f7f;
	for(int i=0;i<K;i++){
		if(dp[i]>maxnum){
			maxnum = dp[i];
			t = i;
		}
	}
	printf("%d %d %d\n",dp[t],a[site[t]],a[t]);
	
	return 0;
} 

1008 Elevator (20 分)

算法标签: 模拟
注意点: 按时间T模拟电梯升降即可

#include<bits/stdc++.h>
using namespace std;

int main(){
	int now = 0;
	int N;
	scanf("%d",&N);
	long long cost = 0;
	for(int i=0;i<N;i++){
		int t;
		scanf("%d",&t);
		if(t>now){
			cost += (t-now)*6;
			cost += 5;
		}else if(now==t){
			cost += 5;
		}else{
			cost += (now-t)*4;
			cost += 5;
		}
		now = t;
	}
	printf("%lld\n",cost);
	
	return 0;
} 

1009 Product of Polynomials (25 分)

算法标签: 模拟 + 高精
注意点: 多项式乘法,本质上和高精度乘法一样,都是开一个比较大的数组,然后从尾到头依次相乘,公式为 C [ k ] = a [ i ] ∗ b [ j ] , i + j = k C[k]=a[i]*b[j],i+j=k C[k]=a[i]b[j],i+j=k,注意多项式乘法需要处理进位的问题,进位可能有多位
注:P1002/P1009可一起做,方法类似

#include<bits/stdc++.h>
using namespace std;
double a[2005];
double b[2005];
double c[2005];
int main(){
	int K;
	int emax = -1;
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));
	
	scanf("%d",&K);
	for(int i=1;i<=K;i++){
		int e;
		double coeff;
		scanf("%d%lf",&e,&coeff);
		emax = max(emax,e);
		a[e] = coeff;
	}
	
	scanf("%d",&K);
	for(int i=1;i<=K;i++){
		int e;
		double coeff;
		scanf("%d%lf",&e,&coeff);
		emax = max(emax,e); 
		b[e] = coeff;
	}
	
	for(int i=emax;i>=0;i--){
		for(int j=emax;j>=0;j--){
			if(a[i]!=0.0 && b[j]!=0.0){
				c[i+j] += a[i] * b[j];
			}
		}
	}
	
	int cnt = 0;
	for(int i=2*emax;i>=0;i--){
		if(c[i]!=0.0){
			cnt++;
		}
	}
	
	cout << cnt;
	for(int i=2*emax;i>=0;i--){
		if(c[i]!=0.0){
			printf(" ");
			printf("%d %.1lf",i,c[i]);
		}
	}
	
	return 0;
} 

1010 Radix (25 分)

算法标签: 数论 + 进制 + 二分
注意点: 一道好题!这道题目把进制扩展到无限大的情况,比如1001进制下的10 ( 1 0 1001 ) (10_{1001}) (101001)就是十进制下的1001 ( 100 1 10 ) (1001_{10}) (100110),这个时候,若采用枚举进制的方法显然会TLE,因此,只能采用二分的方法,枚举进制,若在该进制下的数比预期大,那就缩小进制,否则就扩大,直到缩小的范围为一个数为止,此数即为答案

#include<bits/stdc++.h>
using namespace std;

long long tag,radix;
char N1[15],N2[15];
char temp[15];
int len1,len2;

void convert_N1(long long &num1,long long radix){
	for(int i=0;i<len1;i++){
		if(N1[i]>='a' && N1[i]<='z'){
			num1 = num1*radix + N1[i] - 'a' + 10;	
		}else{
			num1 = num1*radix + N1[i] - '0';
		}
		if(num1<0){
			num1 = -1;
			break;
		}
	}
}

void find_N2_max(long long &minn){
	char max_c=0;
	for(int i=0;i<len2;i++){
		max_c = max(max_c,N2[i]);
	} 
	if(max_c>='a' && max_c<='z'){
		minn = max_c -'a' + 11;
	}else{
		minn = max_c -'0' +1;
	}
}

int cmp(char N2[],long long mid,long long L){
	long long num2 = 0;
	for(int i=0;i<len2;i++){
		if(N2[i]>='a' && N2[i]<='z'){
			num2 = num2*mid + N2[i]-'a'+10;
		}else{
			num2 = num2*mid + N2[i]-'0';
		}
		if(num2<0){
			return 1;
		}
	}
	if(num2==L){
		return 0;
	}else if(num2>L){
		return 1;
	}else{
		return -1; 
	}
}
long long binary_search(long long left,long long right,long long L){
	
	while(left<=right){
		long long mid = (left+right)/2;
		int f = cmp(N2,mid,L);
		if(f==0){
			return mid;
		}else if(f<0){
			left = mid+1;
		}else{
			right = mid-1;
		}
	} 
	return -1;
}

int main(){
	scanf("%s%s%lld%lld",N1,N2,&tag,&radix);
	if(tag == 2){
		swap(N1,N2);
	}
	len1 = strlen(N1);
	len2 = strlen(N2);
	long long num = 0;
	long long left_N,right_N;
	convert_N1(num,radix);
	find_N2_max(left_N);
	right_N = max(left_N,num+1);
	long long ans = binary_search(left_N,right_N,num);
	if(ans == -1){
		printf("Impossible\n");
	}else{
		printf("%lld\n",ans);
	}
	return 0;
} 

1011 World Cup Betting (20 分)

算法标签: 模拟 + 字符串

#include<bits/stdc++.h>
using namespace std;

double a[5][5];
string s = " WTL";

int b[5];

int main(){
	for(int i=1;i<=3;i++){
		for(int j=1;j<=3;j++){
			scanf("%lf",&a[i][j]);
		}
	}
	
	double res = 1.0;
	
	for(int i=1;i<=3;i++){
		double minn = -1.0;
		int site;
		for(int j=1;j<=3;j++){
			if(a[i][j]>minn){
				minn = a[i][j];
				site = j;
			}
		}
		b[i] = site;
		res *= minn;
	}
	res = (res*0.65-1)*2;
	for(int i=1;i<=3;i++){
		printf("%c ",s[b[i]]);
	}
	printf("%.2lf\n",res);
	return 0;
} 

1012 The Best Rank (25 分)

算法标签: 模拟 + 排序

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
struct Student{
	int id;
	int grade[4];
}stu[2010];
char course[10] = {'A','C','M','E'};
int Rank[maxn][5] = {0};
int now;

bool cmp(Student a,Student b){
	return a.grade[now] > b.grade[now];
}

int main(){
	int n,m;
	cin >> n >> m;
	for(int i=0;i<n;i++){
		scanf("%d%d%d%d",&stu[i].id,&stu[i].grade[1],
		&stu[i].grade[2],&stu[i].grade[3]);
		stu[i].grade[0] = (stu[i].grade[1] + stu[i].grade[2] + stu[i].grade[3])/3;
	}
	for(now = 0; now <= 3;now++){
		sort(stu,stu+n,cmp);
		Rank[stu[0].id][now] = 1;
		for(int i=1;i<n;i++){
			if(stu[i].grade[now] == stu[i-1].grade[now]){
				Rank[stu[i].id][now] = Rank[stu[i-1].id][now];
			}else{
				Rank[stu[i].id][now] = i+1;
			}
		}
	}
	
	int q;
	for(int i=0;i<m;i++){
		scanf("%d",&q);
		if(Rank[q][0] == 0){
			cout << "N/A" << endl;
		}else{
			int t = INT_MAX;
			int site = 0;
			for(int j=0;j<=3;j++){
				if(Rank[q][j]<t){
					t = Rank[q][j];
					site = j;
				}
			}
			printf("%d %c\n",t,course[site]);
		}
	}
	return 0;
}

1013 Battle Over Cities (25 分)

算法标签: 图论 + 连通块
注意点: 这道题本质上是求连通块的数量,可采用DFS/BFS的方法进行搜索连通分量,最后所需修建的道路数量即为连通块-1

#include<bits/stdc++.h>
using namespace std;
int N,M,K;
vector<int> G[1005];
bool vis[1005];
void DFS(int u){
	vis[u] = true;
	for(int i=0;i<G[u].size();i++){
		if(!vis[G[u][i]]){
			DFS(G[u][i]);
		}
	}
}
int main(){
	scanf("%d%d%d",&N,&M,&K);
	for(int i=0;i<M;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	for(int i=1;i<=K;i++){
		int t;
		scanf("%d",&t);
		memset(vis,0,sizeof(vis));
		vis[t] = true;
		int cnt = 0;
		for(int j=1;j<=N;j++){
			if(!vis[j]){
				DFS(j);
				cnt++;
			}
		}
		printf("%d\n",cnt-1);
	}
	return 0;
} 

1014 Waiting in Line (30 分)

算法标签: 大模拟
注意点: 一道好题!
\quad\quad 这是一道大模拟的优质题目,模拟了窗口的排队过程,我们需要根据题意明白整个工作流程,根据当前时间(nowtime),服务结束时间(endtime),以及每个窗口的队伍数量封装成一个窗口结构体,依照输入数据的队列,反复取出等待队列的队头,进行服务,快进时间,再将等候区(waiting line)之后的队首取出,插入该窗口的末端

#include<bits/stdc++.h>
using namespace std;
int N,M,K,Q; 

int c[1005];
int qtime[1005];

struct windows{
	int nowtime;
	int endtime;
	queue<int> q;
};
windows w[25];

int time_min(int h,int m){
	return h*60+m;
}

void min_time(int t){
	printf("%02d:%02d\n",t/60,t%60);
}

int main(){
	scanf("%d%d%d%d",&N,&M,&K,&Q);
	for(int i=1;i<=K;i++){
		scanf("%d",&c[i]);
	}
	
	int start = time_min(8,0);
	int end = time_min(17,0);
	 
	for(int i=1;i<=N;i++){
		w[i].nowtime = time_min(8,0);
		w[i].endtime = time_min(8,0);
	}
	int now = 1;
	int maxnum = N*M;
	for(now = 1;now<=K && now<=maxnum;){
		for(int j=1;j<=N;j++){
			if(w[j].q.size()<M){
				if(w[j].endtime >= end){
					w[j].q.push(c[now]);
					now++;
				}else{
					w[j].endtime += c[now];
					qtime[now] = w[j].endtime;
					w[j].q.push(c[now]);
					now++;	
				}
			}
			if(now>K || now>maxnum){
				break;
			}
		}
	}
	
	for(now;now<=K;now++){
		int u = -1;
		int mintime = INT_MAX;
		for(int j=1;j<=N;j++){
			int t = w[j].q.front();
			if(t+w[j].nowtime < mintime){
				mintime = t + w[j].nowtime;
				u = j;
			}
		}
		if(w[u].endtime>=end){
			break;
		}
		int f = w[u].q.front();
		w[u].nowtime += f;
		w[u].q.pop();
		w[u].endtime += c[now];
		w[u].q.push(c[now]); 
		qtime[now] = w[u].endtime;
	}
	
	for(int i=1;i<=Q;i++){
		int t;
		scanf("%d",&t);
		if(qtime[t]==0){
			printf("Sorry\n");
		}else{
			min_time(qtime[t]);
		}
	}
	
	return 0;
}

1015 Reversible Primes (20 分)

算法标签: 数论 + 素数
注意点: 可用素数筛预处理素数集合,加快程序处理速度

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
bool p[maxn] = {1,1,0};
void init(){
	for(int i=2;i<maxn;i++){
		if(!p[i]){
			for(int j=2*i;j<maxn;j+=i){
				p[j] = 1;
			}
		}
	}
}
int main(){
	init();
	int n;
	int D;
	while(scanf("%d",&n)!=EOF){
		if(n<0){
			break;
		}
		scanf("%d",&D);
		if(!p[n]){
			int ans = 0;
			while(n){
				ans = ans*D + (n%D);
				n/=D;
			}		
			if(!p[ans]){
				printf("Yes\n");
			}else{
				printf("No\n");
			}
		}else{
			printf("No\n");
		}
	}
	
	
	return 0;
}

1016 Phone Bills (25 分)

算法标签: 模拟 + 排序

#include<bits/stdc++.h>
using namespace std;
int a[30];

struct info{
	string name;
	int month;
	int day;
	int hour;
	int min;
	int status;
};
info in[1005];

bool cmp(info i1,info i2){
	if(i1.name!=i2.name){
		return i1.name < i2.name;
	}else if(i1.month!=i2.month){
		return i1.month < i2.month;
	}else if(i1.day!=i2.day){
		return i1.day < i2.day;
	}else if(i1.hour!=i2.hour){
		return i1.hour < i2.hour;
	}else{
		return i1.min < i2.min;
	}
}

int main(){
	for(int i=0;i<24;i++){
		cin >> a[i];
	}
	int N;
	cin >> N;
	for(int i=0;i<N;i++){
		cin >> in[i].name;
		scanf("%d:%d:%d:%d",&in[i].month,&in[i].day,&in[i].hour,&in[i].min);
		string t;
		cin >> t;
		if(t == "on-line"){
			in[i].status = 0;
		}else{
			in[i].status = 1;
		} 
	}
	sort(in,in+N,cmp);
	
	int cnt = 0;
	double total = 0;
	for(int i=1;i<=N;i++){
		if(in[i-1].name == in[i].name){
			if(in[i-1].status == 0 && in[i].status == 1){
				if(cnt == 0){
					cout << in[i].name << " ";
					printf("%02d\n",in[i].month);
				}
				printf("%02d:%02d:%02d %02d:%02d:%02d",in[i-1].day,in[i-1].hour,in[i-1].min,
				in[i].day,in[i].hour,in[i].min);
				int d1 = in[i-1].day;
				int h1 = in[i-1].hour;
				int m1 = in[i-1].min;
				int d2 = in[i].day;
				int h2 = in[i].hour;
				int m2 = in[i].min;
				int fee = 0;
				int count = 0;
				while(d1<d2 || h1<h2 || m1<m2){
					count++;
					m1++;
					fee += a[h1];
					if(m1==60){
						m1 = 0;
						h1 ++;
					}
					if(h1==24){
						h1 = 0;
						d1 ++;
					}
				}
				cnt++;
				double res = 1.0*fee/100.0;
				total += res;
				printf(" %d $%.2lf\n",count,res);
			}
		}else{
			if(cnt){
				printf("Total amount: $%.2lf\n",total);
			}
			total = 0.0;
			cnt = 0;
		}
	}
	return 0;
} 

1017 Queueing at Bank (25 分)

算法标签: 大模拟
注意点: 一道好题!建议与P1014进行对比
这道题本质上是大模拟,需要对整个模拟的流程模块化处理,这里需要注意到达时间、开始服务时间、结束时间是3个不同的概念!

#include<bits/stdc++.h>
using namespace std;
int N,K;
struct custom{
	int arrival;
	int last;
};
custom c;
int converttime(int h,int m,int s){
	return h*3600 + m*60 + s;
}
vector<custom> v;
bool cmp(custom c1,custom c2){
	return c1.arrival < c2.arrival;
}
int w[105];

int main(){
	scanf("%d%d",&N,&K);
	int start = converttime(8,0,0);
	int end = converttime(17,0,0);
	for(int i=0;i<N;i++){
		char time[105];
		int servertime;
		scanf("%s%d",time,&servertime);
		int h,m,d;
		h = 10*(time[0]-'0') + (time[1]-'0');
		m = 10*(time[3]-'0') + (time[4]-'0');
		d = 10*(time[6]-'0') + (time[7]-'0');
		int t = converttime(h,m,d);
		if(t>end){
			continue;
		}else{
			c.arrival = t;
			c.last = servertime;
			v.push_back(c);
		}
	}
	sort(v.begin(),v.end(),cmp);
	for(int i=1;i<=K;i++){
		w[i] = start;
	}
	int total = 0;
	double ave = 0.0;
	for(int i=0;i<v.size();i++){
		int u = -1;
		int mintime = INT_MAX;
		for(int j=1;j<=K;j++){
			if(w[j]<mintime){
				mintime = w[j];
				u = j;
			}
		}
		if(w[u]<=v[i].arrival){
			w[u] = v[i].arrival + v[i].last*60;
		}else{
			total += (w[u]-v[i].arrival);
			w[u] += v[i].last*60;
		}
	}
	ave = total/60.0/(v.size()*1.0);
	printf("%.1lf\n",ave);
	return 0;
} 

1018 Public Bike Management (30 分)

算法标签: 图论 + Dijkstra + DFS
注意点: 本题是Dijkstra的进化版本,即带DFS的Dijkstra,DFS的目的是提前存储可能的路径顶点(dijkstra算法中保存),完成最短路算法之后,我们再对保存的路径进行搜索,取出满足题意最大的结果,输出。
注意此题与P1003的对比!

#include<bits/stdc++.h>
using namespace std;
int Cmax,N,SP,M;
struct node{
	int v;
	int dis;
};

bool vis[505];
int dp[505];
int weight[505];
vector<node> G[505];
vector<int> pre[505];
vector<int> ans;
vector<int> tempans;
int sendmax = INT_MAX;
int take;

void dijstra(int s){
	fill(dp,dp+N+1,INT_MAX);
	dp[s] = 0;
	memset(vis,0,sizeof(vis));
	for(int i=0;i<N+1;i++){
		int u = -1;
		int minnum = INT_MAX;
		for(int j=0;j<=N;j++){
			if(!vis[j] && dp[j]<minnum){
				minnum = dp[j];
				u = j;
			}
		}
		if(u==-1){
			return;
		}
		vis[u] = true;
		for(int j=0;j<G[u].size();j++){
			int v = G[u][j].v;
			int dis = G[u][j].dis;
			if(!vis[v]){
				if(dp[u]+dis<dp[v]){
					dp[v] = dp[u] + dis;
					pre[v].clear();
					pre[v].push_back(u);
				}else if(dp[u]+dis==dp[v]){
					pre[v].push_back(u);
				}
			}
		}
	}
}

void dfs(int v){
	if(v == 0){
		int Need = 0;
		int Remain = 0;
		tempans.push_back(v);
		for(int i=tempans.size()-2;i>=0;i--){
			if(weight[tempans[i]]>0){
				Remain += weight[tempans[i]];
			}else{
				if(Remain>=abs(weight[tempans[i]])){
					Remain -= abs(weight[tempans[i]]);
				}else{
					Need += (abs(weight[tempans[i]])-Remain);
					Remain = 0;
				}
			}
		}
		if(Need<sendmax){
			sendmax = Need;
			ans = tempans;
			take = Remain;
		}else if(Need == sendmax){
			if(Remain<take){
				take = Remain;
				ans = tempans;
			}
		}
		tempans.pop_back();
		return;
	}
	tempans.push_back(v);
	for(int i=0;i<pre[v].size();i++){
		dfs(pre[v][i]);
	}
	tempans.pop_back();
}

int main(){
	cin >> Cmax >> N >> SP >> M;
	for(int i=1;i<=N;i++){
		cin >> weight[i];
	}
	for(int i=0;i<M;i++){
		int c1,c2,l;
		cin >> c1 >> c2 >> l;
		node temp;
		temp.v = c2;
		temp.dis = l;
		G[c1].push_back(temp);
		temp.v = c1;
		G[c2].push_back(temp);
	}
	for(int i=1;i<=N;i++){
		weight[i] -= Cmax/2;
	}
	dijstra(0);
	
	dfs(SP);
	printf("%d ",sendmax);
	for(int i=ans.size()-1;i>=0;i--){
		if(i==ans.size()-1){
			printf("%d",ans[i]);
		}else{
			printf("->%d",ans[i]);
		}
	}
	printf(" %d\n",take);
	
	return 0;
} 

1019 General Palindromic Number (20 分)

算法标签: 数论 + 模拟
注意点: 回文数的判断,最基本的算法是遍历前半段 O ( n 2 ) O(\frac{n}{2}) O(2n)个下标,观察其与后半段是否相等,相等即是回文数

#include<bits/stdc++.h>
using namespace std;
int a[105];
int main(){
	int n,b;
	cin >> n >> b;
	int cnt = 0;
	while(n){
		a[cnt++] = n%b; 
		n/=b;
	}
	bool flag = true;
	for(int i=0;i<cnt/2;i++){
		if(a[i] == a[cnt-i-1]){
			continue;
		}else{
			flag = false;
		}
	}
	if(flag){
		cout << "Yes" << endl;
	}else{
		cout << "No" << endl;
	}
	for(int i=cnt-1;i>=0;i--){
		if(i!=0){
			cout << a[i] << " ";
		}else{
			cout << a[i] << endl;
		}
	}
	return 0;
}

1020 Tree Traversals (25 分)

算法标签: 树,二叉树 + 遍历
注意点: 首先输入中序遍历和后序遍历,建立一棵树,然后从根结点出发,进行层次遍历

#include<bits/stdc++.h>
using namespace std;

int post[35];
int in[35];
struct node{
	int data;
	node* lchild;
	node* rchild;
};
node* root = NULL;
node* newnode(int v){
	node* Node = new node;
	Node->data = v;
	Node->lchild = NULL;
	Node->rchild = NULL; 
	return Node;	
} 
node* Create(int inL,int inR,int postL,int postR){
	if(postL>postR){
		return NULL;
	}
	int d = post[postR];
	int k;
	for(int i=inL;i<=inR;i++){
		if(in[i]==d){
			k = i;
			break;
		}
	}
	int numleft = k-inL;
	node* Node = new node;
	Node->data = d; 
	Node->lchild = Create(inL,k-1,postL,postL+numleft-1);
	Node->rchild = Create(k+1,inR,postL+numleft,postR-1); 
	return Node;
}
queue<node*> q;
int n;
void Level(node* root){
	int T = n;
	q.push(root);
	while(!q.empty()){
		node* f = q.front();
		q.pop();
		if(T==1){
			printf("%d\n",f->data);
		}else{
			printf("%d ",f->data);
		}
		T--;
		if(f->lchild){
			q.push(f->lchild);
		}
		if(f->rchild){
			q.push(f->rchild);
		}
	}
}
int main(){
	cin >> n;
	for(int i=0;i<n;i++){
		cin >> post[i];
	}	
	for(int i=0;i<n;i++){
		cin >> in[i];
	}
	root = Create(0,n-1,0,n-1);
	Level(root);
	return 0;
}

1021 Deepest Root (25 分)

算法标签: 树,二叉树
注意点: 一道好题!这道题目需要求出一棵树上最远的点集,也就是说,假设有一个点集A,另一个点集B,A中任意一点到B中任意一点的距离与树中最远两个顶点的距离相同,那么这就是Deepest Root!
以下我们不加证明的给出这道题的解法(详细解法可参考相应的数学证明):
1.首先从任意一点出发,遍历到最深的点,依次记录,这些点就是点集A
2.从点集A的任意一点出发,遍历最深的点,依次记录,得到点集B
3.A+B即为题目所求

#include<bits/stdc++.h>
using namespace std;
vector<int> G[10005];
bool vis[10005];
set<int> ans1;
set<int> ans2;
set<int> ans;

void dfs(int u){
	vis[u] = true;
	for(int i=0;i<G[u].size();i++){
		if(!vis[G[u][i]]){
			dfs(G[u][i]);
		} 
	}
}

void dfs1(int u,int depth,int &maxdepth){
	vis[u] = true;
	if(depth>maxdepth){
		ans1.clear();
		maxdepth = depth;
		ans1.insert(u);
	}else if(depth==maxdepth){
		ans1.insert(u);
	}
	for(int i=0;i<G[u].size();i++){
		if(!vis[G[u][i]]){
			dfs1(G[u][i],depth+1,maxdepth);
		}
	}
}

void dfs2(int u,int depth,int &maxdepth){
	vis[u] = true;
	if(depth>maxdepth){
		ans2.clear();
		maxdepth = depth;
		ans2.insert(u);
	}else if(depth==maxdepth){
		ans2.insert(u);
	}
	
	for(int i=0;i<G[u].size();i++){
		if(!vis[G[u][i]]){
			dfs2(G[u][i],depth+1,maxdepth);
		}
	}
}

int main(){
	int N;
	scanf("%d",&N);
	for(int i=1;i<N;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	int cnt = 0;
	for(int i=1;i<=N;i++){
		if(!vis[i]){
			dfs(i);
			cnt++;
		}
	}
	if(cnt>1){
		printf("Error: %d components\n",cnt);
	}else{
		memset(vis,0,sizeof(vis));
		int maxdepth = -1;
		dfs1(1,0,maxdepth);
		memset(vis,0,sizeof(vis));
		maxdepth = -1;
		dfs2(*ans1.begin(),0,maxdepth);
		
		for(auto it=ans1.begin();it!=ans1.end();it++){
			ans.insert(*it);
		}
		for(auto it=ans2.begin();it!=ans2.end();it++){
			ans.insert(*it);
		}
		for(auto it=ans.begin();it!=ans.end();it++){
			printf("%d\n",*it);
		}
	}
	return 0;
} 

1022 Digital Library (30 分)

算法标签: 排序,哈希

#include<bits/stdc++.h>
using namespace std;
int N;
map<string,set<int> > mptitle,mpname,mpword,mppublisher,mpyear;
void input(){
	cin >> N;
	string title,name,word,publisher,year;
	for(int i=0;i<N;i++){
		int ID;
		cin >> ID;
		getchar();
		getline(cin,title);
		mptitle[title].insert(ID);
		getline(cin,name);
		mpname[name].insert(ID);
		while(1){
			cin >> word;
			mpword[word].insert(ID);
			char c = getchar();
			if(c=='\n'){
				break;
			}
		}
		getline(cin,publisher);
		mppublisher[publisher].insert(ID);
		getline(cin,year);
		mpyear[year].insert(ID);
	}
}
void print(map<string,set<int> > &mp,string s){
	if(mp.find(s)!=mp.end()){
		for(auto it = mp[s].begin();it!=mp[s].end();it++){
			printf("%07d\n",*it);
		}	
	}else{
		cout << "Not Found" << endl;
	} 
	
}
void query(){
	int M;
	cin >> M;
	for(int i=0;i<M;i++){
		int type;
		scanf("%d: ",&type);
		printf("%d: ",type);
		string q;
		getline(cin,q);
		cout << q << endl;
		if(type == 1){
			print(mptitle,q);
		}else if(type == 2){
			print(mpname,q); 
		}else if(type == 3){
			print(mpword,q);
		}else if(type == 4){
			print(mppublisher,q);
		}else{
			print(mpyear,q);
		} 
	}
}
int main(){
	input();
	query();
	
	return 0;
}

1023 Have Fun with Numbers (20 分)

算法标签: 数论 + 高精

#include<bits/stdc++.h>
using namespace std;
struct bign{
	int len;
	int a[1005];
	bign(){
		memset(a,0,sizeof(a));
		len = 0;
	}
};
bign b1;
bign b2;
int n1[15];
int n2[15];
int main(){
	string s;
	cin >> s;
	int len = s.size();
	b1.len = len;
	for(int i=len-1;i>=0;i--){
		b1.a[len-i-1] = s[i]-'0';
	}
	int jw = 0;
	for(int i=0;i<len;i++){
		b2.a[i] = b1.a[i]*2 + jw;
		jw = b2.a[i]/10;
		b2.a[i] %= 10;
	}
	if(jw){
		b2.a[len] = jw;
		b2.len = b1.len+1;
	}else{
		b2.len = b1.len;
	}
	for(int i=0;i<b1.len;i++){
		n1[b1.a[i]%10]++;
	}
	for(int i=0;i<b2.len;i++){
		n2[b2.a[i]%10]++;
	}
	bool f = true;
	for(int i=0;i<=9;i++){
		if(n1[i] == n2[i]){
			continue;
		}else{
			f = false;
			break;
		}
	}
	if(f){
		printf("Yes\n");
	}else{
		printf("No\n");
	}
	for(int i=b2.len-1;i>=0;i--){
		printf("%d",b2.a[i]);
	}
	printf("\n");
	return 0;
} 

1024 Palindromic Number (25 分)

算法标签: 数论 + 高精 + 字符串

#include<bits/stdc++.h>
using namespace std;
struct bign{
	int len;
	int a[1005];
	bign(){
		memset(a,0,sizeof(a));
		len = 0;
	}
};

bign x1;
bign x2;
bign x3;

bool isPalin(bign x){
	bool f = true;
	for(int i=0;i<x.len/2;i++){
		if(x.a[i] == x.a[x.len-1-i]){
			continue;
		}else{
			f = false;
			break;
		}
	}
	return f;
}

int main(){
	string N;
	int K;
	cin >> N;
	cin >> K; 
	int l = N.size();
	for(int i=0;i<l;i++){
		x1.a[i] = N[i]-'0';
	}
	for(int i=0;i<l;i++){
		x2.a[l-i-1] = N[i] - '0';
	}

	x1.len = l;
	x2.len = l;
	int cnt = 0;
	
	if(isPalin(x1)){
		cout << N << endl;
		printf("0\n");
		return 0;
	}
	
	while(K--){
		cnt++;
		int jw = 0;
		for(int i=0;i<x1.len;i++){
			x3.a[i] = x1.a[i] + x2.a[i] + jw;
			jw = x3.a[i] / 10;
			x3.a[i] %= 10;
		}
		if(jw){
			x3.a[x1.len] = jw;
			x3.len = x1.len+1;
		}else{
			x3.len = x1.len;
		}
		if(isPalin(x3)){
			break;
		}
		for(int i=0;i<x3.len;i++){
			x1.a[i] = x3.a[i];
			x2.a[x3.len-i-1] = x3.a[i];
		} 
		x1.len = x3.len;
		x2.len = x3.len;
	}
	
	for(int i=x3.len-1;i>=0;i--){
		printf("%d",x3.a[i]);
	}
	printf("\n");
	printf("%d\n",cnt);
	return 0;
} 

1025 PAT Ranking (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;

struct student{
	long long id;
	int score;
	int final_rank;
	int local_num;
	int local_rank;
};

student s[30005];

bool cmp(student s1,student s2){
	if(s1.score!=s2.score){
		return s1.score > s2.score;
	}else{
		return s1.id < s2.id;
	}
}

int main(){
	int N;
	cin >> N;
	int cnt = 0;
	int class_num = 1;
	for(int i=0;i<N;i++){
		int K;
		cin >> K;
		for(int j=0;j<K;j++){
			scanf("%lld%d",&s[cnt].id,&s[cnt].score);
			s[cnt++].local_num = class_num;
		}
		class_num++;
		
		sort(s+cnt-K,s+cnt,cmp);
		s[cnt-K].local_rank = 1;
		for(int j=1;j<K;j++){
			if(s[cnt-K+j].score == s[cnt-K+j-1].score){
				s[cnt-K+j].local_rank = s[cnt-K+j-1].local_rank;
			}else{
				s[cnt-K+j].local_rank = j+1;
			}
		}
	}
	
	sort(s,s+cnt,cmp);
	s[0].final_rank = 1;
	for(int j=1;j<cnt;j++){
		if(s[j].score == s[j-1].score){
			s[j].final_rank = s[j-1].final_rank;
		}else{
			s[j].final_rank = j+1;
		}
	}
	if(cnt){
		cout << cnt << endl; 
		for(int i=0;i<cnt;i++){
			printf("%013lld %d %d %d\n",s[i].id,s[i].final_rank,s[i].local_num,s[i].local_rank); 
		}	
	}
	
	return 0;
} 

1026 Table Tennis (30 分)

算法标签: 大模拟
注意点: 一道好题!这道大模拟是几百题之中最难的一道
首先我们需要明白题目的意思,题目是想让我们模拟球馆的场地分配,每组人来,就分配相应的场地。按照先到先得,VIP优先预置的策略,模拟一天的分配,根据这两个策略,可分成如下4类讨论:(变量有顾客(VIP)、球桌(VIP))
1.(当前来到的)是VIP顾客,(当前空闲的且编号最小)是VIP球桌,此时直接分配[当前顾客使用当前球桌]
2.是VIP顾客,不是VIP球桌,这时候,我们需要遍历所有的VIP球桌,如果球桌使用的结束时间(endtime) < = <= <=顾客的到达时间(arrivetime),那么就分配VIP编号中最小的(且满足条件),否则就分配普通球桌中编号最小的(且满足条件)
3.不是VIP顾客,是VIP球桌,此时需扫描VIP队列中的队首,若VIP顾客的到达时间(arrivetime) > = >= >=球桌使用的结束时间(endtime),那么这张桌子应该预留给VIP顾客,而不是普通顾客,若找不到满足上述条件的VIP顾客,我们才将该VIP桌子分配给普通顾客
4.不是VIP顾客,也不是VIP球桌,此时直接分配即可

#include<bits/stdc++.h>
using namespace std;
int N,K,M;

struct player{
	int arrivetime;
	int starttime;
	int traintime;
	bool isVIP;
};
player tempP;

struct table{
	int endtime;
	int num;
	bool isVIP;
};

table t[105];
vector<player> v;

bool cmp1(player p1,player p2){
	return p1.arrivetime < p2.arrivetime;
}
bool cmp2(player p1,player p2){
	if(p1.starttime!=p2.starttime){
		return p1.starttime < p2.starttime;
	}else{
		return p1.isVIP > p2.isVIP;
	}
}

int nextVIP(int k){
	k++;
	while(k<v.size() && v[k].isVIP == 0){
		k++;
	}
	return k;
}
int converttime(int h,int m,int s){
	return h*3600 + m*60 +s;
}
void allocate(int pID,int tID){
	if(v[pID].arrivetime<=t[tID].endtime){
		v[pID].starttime = t[tID].endtime;
	}else{
		v[pID].starttime = v[pID].arrivetime;
	}
	t[tID].endtime = v[pID].starttime + v[pID].traintime;
	t[tID].num++;
}

int main(){
	scanf("%d",&N);
	int start = converttime(8,0,0);
	int end = converttime(21,0,0);
	for(int i=0;i<N;i++){
		int h,m,d;
		int last;
		int isVIP;
		scanf("%d:%d:%d%d%d",&h,&m,&d,&last,&isVIP);
		last = min(last,120);
		tempP.arrivetime = converttime(h,m,d);
		if(tempP.arrivetime>=end){
			continue;
		}else{
			tempP.isVIP = isVIP;
			tempP.starttime = end;
			tempP.traintime = last*60;
			v.push_back(tempP);
		}	
	}
	scanf("%d%d",&K,&M);
	for(int i=1;i<=K;i++){
		t[i].endtime = start;
		t[i].num = 0;
		t[i].isVIP = 0;
	}
	for(int i=0;i<M;i++){
		int number;
		scanf("%d",&number);
		t[number].isVIP = 1;
	}
	sort(v.begin(),v.end(),cmp1);
	int i = 0,VIPnow = -1;
	VIPnow = nextVIP(VIPnow);
	while(i<v.size()){
		int u = -1;
		int mintime = INT_MAX;
		for(int j=1;j<=K;j++){
			if(t[j].endtime < mintime){
				mintime = t[j].endtime;
				u = j;
				if(t[j].endtime <= v[i].arrivetime){
					break;
				}
			}
		}
		if(t[u].endtime>=end){
			break;
		}
		if(v[i].isVIP == 1 && i<VIPnow){
			i++;
			continue;
		}
		if(t[u].isVIP == 1){
			if(v[i].isVIP == 1){
				allocate(i,u);
				if(i == VIPnow){
					VIPnow = nextVIP(VIPnow);
				}
				i++;
			}else{
				if(VIPnow<v.size() && v[VIPnow].arrivetime<=t[u].endtime){
					allocate(VIPnow,u);
					VIPnow = nextVIP(VIPnow);
				}else{
					allocate(i,u);
					i++;
				} 
			}
		}else{
			if(v[i].isVIP == 0){
				allocate(i,u);
				i++;
			}else{
				int uu=-1;
				int mmintime = INT_MAX;
				for(int j=1;j<=K;j++){
					if(t[j].isVIP ==1 && t[j].endtime<mmintime){
						mmintime = t[j].endtime;
						uu=j;
					}
				}
				if(uu!=-1 && (t[uu].endtime <= v[i].arrivetime)){
					allocate(i,uu);
					if(VIPnow == i){
						VIPnow = nextVIP(VIPnow);
					}
					i++;
				}else{
					allocate(i,u);
					if(VIPnow == i){
						VIPnow = nextVIP(VIPnow);
					}
					i++;
				}
			}
		}
	}
	sort(v.begin(),v.end(),cmp2);
	for(int i=0;i<v.size() && v[i].starttime<end;i++){
		int t1 = v[i].arrivetime;
		int t2 = v[i].starttime;
		printf("%02d:%02d:%02d ",t1/3600,t1/60%60,t1%60);
		printf("%02d:%02d:%02d ",t2/3600,t2/60%60,t2%60);
		printf("%.0lf\n",round((t2-t1)/60.0));
	}
	for(int j=1;j<=K;j++){
		if(j==1){
			printf("%d",t[j].num);
		}else{
			printf(" %d",t[j].num);
		}
	}
	
	return 0;
}

1027 Colors in Mars (20 分)

算法标签: 模拟 + 字符串

#include<bits/stdc++.h>
using namespace std;
string s = "0123456789ABC";
int main(){
	cout << "#";
	for(int i=1;i<=3;i++){
		int t;
		cin >> t;
		int a,b;
		a = t/13;
		b = t%13;
		cout << s[a] << s[b];
	}
	
	return 0;
} 

1028 List Sorting (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
struct stu{
	int id;
	string name;
	int grade;
};
stu s[100005];

bool cmp1(stu s1,stu s2){
	return s1.id < s2.id;
}

bool cmp2(stu s1,stu s2){
	if(s1.name!=s2.name){
		return s1.name < s2.name;
	}else{
		return s1.id < s2.id;
	}
}

bool cmp3(stu s1,stu s2){
	if(s1.grade!=s2.grade){
		return s1.grade < s2.grade;
	}else{
		return s1.id < s2.id;
	}
}

int main(){
	cin.tie(0);
	cout.tie(0);
	int N,C;
	cin >> N >> C;
	for(int i=0;i<N;i++){
		scanf("%d",&s[i].id);
		cin >> s[i].name;
		scanf("%d",&s[i].grade);
	}
	
	if(C==1){
		sort(s,s+N,cmp1);
	}else if(C==2){
		sort(s,s+N,cmp2);
	}else{
		sort(s,s+N,cmp3);
	}
	for(int i=0;i<N;i++){
		printf("%06d ",s[i].id);
		cout << s[i].name;
		printf(" %d\n",s[i].grade);
	} 
	
	return 0;
} 

1029 Median (25 分)

算法标签: 数论 + 中位数
注意点: 中位数算法,由于题目中给出的数据范围很大,因此排序求中位数不是很好的选择,我们采用枚举的方法,不断从A序列和B序列中取出队首元素,进行比较,小的元素计入,这样通过 O ( n ) O(n) O(n)的时间得到了中位数

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int a[maxn];
int b[maxn];

int main(){
	int p,q;
	scanf("%d",&p);
	for(int i=0;i<p;i++){
		scanf("%d",&a[i]);
	}
	a[p] = INT_MAX;
	scanf("%d",&q);
	for(int i=0;i<q;i++){
		scanf("%d",&b[i]);
	} 
	b[q] = INT_MAX;
	
	int i = 0;
	int j = 0;
	int median = (p+q-1)/2;
	int cnt = 0;
	while(cnt<median){
		if(a[i]<b[j]){
			i++;
		}else{
			j++;
		}
		cnt++;
	}
	if(a[i]<b[j]){
		printf("%d\n",a[i]);
	}else{
		printf("%d\n",b[j]);
	}
	return 0;
} 

1030 Travel Plan (30 分)

算法标签: 图论 + Dijkstra + DFS
注意点: 和之前几道图论的题目类似,可参考P1003/P1018的解法

#include<bits/stdc++.h>
using namespace std;
int N,M,S,D;
struct node{
	int v;
	int dis;
	int c;
};
vector<node> G[505];
int dp[505];
int cost[505];
bool vis[505];
int pre[505];

void dijstra(int s){
	fill(dp,dp+N,INT_MAX);
	fill(cost,cost+N,INT_MAX);
	dp[s] = 0;
	cost[s] = 0;
	for(int i=0;i<N;i++){
		int u = -1;
		int minnum = INT_MAX;
		for(int j=0;j<N;j++){
			if(!vis[j] && dp[j]<minnum){
				minnum = dp[j];
				u = j;
			}
		}
		if(u==-1){
			return;
		} 
		vis[u] = true;
		for(int j=0;j<G[u].size();j++){
			int v = G[u][j].v;
			int dis = G[u][j].dis;
			int c = G[u][j].c;
			if(!vis[v]){
				if(dp[u]+dis<dp[v]){
					dp[v] = dp[u] + dis;
					cost[v] = cost[u] +c;
					pre[v] = u;
				}else if(dp[u]+dis==dp[v]){
					if(cost[u]+c<cost[v]){
						cost[v] = cost[u] + c;
						pre[v] = u;
					}
				}	
			}
		}
	}
}

void printpath(int D){
	if(D==S){
		printf("%d ",S);
		return;
	}
	printpath(pre[D]);
	printf("%d ",D);
}

int main(){
	scanf("%d%d%d%d",&N,&M,&S,&D);
	for(int i=0;i<M;i++){
		int c1,c2,l,c;
		scanf("%d%d%d%d",&c1,&c2,&l,&c);
		node temp;
		temp.v = c2;
		temp.dis = l;
		temp.c = c;
		G[c1].push_back(temp);
		temp.v = c1;
		G[c2].push_back(temp);
	}
	dijstra(S);
	printpath(D);
	printf("%d ",dp[D]);
	printf("%d\n",cost[D]);
	return 0;
} 

1031 Hello World for U (20 分)

算法标签: 模拟 + 字符串
注意点: 这道题目需要求出打印的字符串横竖的长度,其中竖向高度为 n 1 = n 3 = N + 2 3 n_1=n_3=\frac{N+2}{3} n1=n3=3N+2,横向的长度为 n 2 = ( N + 2 ) − n 1 − n 3 n_2=(N+2)-n_1-n_3 n2=(N+2)n1n3,按照长度顺序依次输出即可

#include<bits/stdc++.h>
using namespace std;

int main(){
	string s;
	cin >> s;
	int N = s.size();
	int n1,n3;
	n1 = n3 = (N+2)/3;
	int n2 = N+2 - n1 - n3;
	for(int i=0;i<n1-1;i++){
		cout << s[i];
		for(int j=1;j<n2-1;j++){
			cout << " ";
		}
		cout << s[N-1-i];
		cout << endl;
	}
	for(int j=0;j<n2;j++){
		cout << s[n1-1+j];
	}
	return 0;
}

1032 Sharing (25 分)

算法标签: 字符串 + 链表
注意点: 求解两个链表的最大公共后缀长度,可以在每个结点增添flag标记,首先遍历链表1,把经过的结点flag标记为true,然后遍历链表2,第一次找到flag为true的标签,从此之后都为公共后缀,输出结点地址即可

#include<bits/stdc++.h>
using namespace std;
struct node{
	char value;
	int next;
	bool flag = false;
};
const int maxn = 1e5+5;
node n[maxn];

int main(){
	int start1,start2;
	int N;
	scanf("%d%d%d",&start1,&start2,&N);
	for(int i=0;i<N;i++){
		int t;
		scanf("%d ",&t);
		scanf("%c %d",&n[t].value,&n[t].next);
	}	
	while(start1!=-1){
		n[start1].flag = true;
		start1 = n[start1].next;
	}
	while(start2!=-1){
		if(n[start2].flag==true){
			break;
		}else{
			start2 = n[start2].next;
		}
	}
	if(start2==-1){
		printf("-1\n");
	}else{
		printf("%05d\n",start2);
	}
	return 0;
}

1033 To Fill or Not to Fill (25 分)

算法标签: 贪心
注意点: 一道好题!这是一道贪心算法的经典题目,我们可以从起点出发,模拟整个路程中的贪心过程。
1.首先,从起点出发,计算满油能开的最远距离,然后在这个距离内,找到一个最便宜的加油站,计算到这个加油站所需加的最少油量,若找不到,则在起点加满油,开到最近的下一个加油站。
2.然后,在下一个加油站处,仍旧计算满油能开的最远距离,找到一个最便宜的加油站,计算到这个加油站所需加的最少油量,若找不到,则在该加油站处加满油,开到最近的下一个加油站
3.如此反复循环,直到终点或不可达
不可达输出不可达,可达则输出最小花费

#include<bits/stdc++.h>
using namespace std;
struct gas_station{
	double price;
	int distance;
};
gas_station g[1005];
bool cmp(gas_station g1,gas_station g2){
	return g1.distance < g2.distance;
}
int main(){
	int Cmax,D,per,n;
	scanf("%d%d%d%d",&Cmax,&D,&per,&n);
	for(int i=0;i<n;i++){
		scanf("%lf%d",&g[i].price,&g[i].distance);
	}
	g[n].distance = D;
	g[n].price = 0.0;
	sort(g,g+n,cmp);
	if(g[0].distance!=0){
		printf("The maximum travel distance = 0.00\n");
		return 0;
	}
	double far_dis = 1.0*Cmax*per;
	int now = 0;
	double Cur = 0.0;
	double total = 0.0;
	
	while(now<n){
		int next = -1;
		if(g[now+1].distance-g[now].distance>far_dis){
			break;
		}
		for(int i=now+1;i<=n;i++){
			if(far_dis+g[now].distance>=g[i].distance){
				if(g[i].price<g[now].price){
					next = i;
					break;
				}
			}else{
				break;
			}
		}
		if(next == -1){
			double gas_price = (Cmax - Cur)*g[now].price;
			Cur = Cmax*1.0;
			Cur = Cur - (g[now+1].distance-g[now].distance)*1.0/(per*1.0);
			total += gas_price;
			now++;
		}else{
			double gas_need = (g[next].distance-g[now].distance)*1.0/(per*1.0);
			if(Cur>gas_need){
				Cur -= gas_need;
			}else{
				double gas_price = (gas_need-Cur)*g[now].price; 
				total += gas_price;
				Cur = 0.0;
			}
			now = next;
		}
	}
	
	if(now == n){
		printf("%.2lf\n",total);
	}else{
		printf("The maximum travel distance = %.2lf\n",g[now].distance+far_dis);
	}
	return 0;
} 

1034 Head of a Gang (30 分)

算法标签: 贪心
注意点: 看似是一道并查集操作,实际上是图论的DFS搜索,统计一个连通块内顶点的数量难度相对不大,但是统计边权之和是本题的难度所在,如果一个连通块中,不存在环,边权直接相加即可,但是本题中可能出现环,此时要先加边权,加完边权置为0(防止重复累加边权),再访问下一个顶点,这样能够保证有边就加(不少加边权),如此才能统计出正确的结果,gang是指点权最大的点,每访问一个点,实时更新gang的归属即可。

#include<bits/stdc++.h>
using namespace std;
int N,K;
map<string,int> strtonum;
map<int,string> numtostr;
map<string,int> TotalFee;

int edge[2005][2005];
bool f[2005];
int cnt = 0;
int maxn = -1;

void DFS(int u,int &gang,int &groupnum,int &total){
	if(TotalFee[numtostr[u]]>maxn){
		maxn = TotalFee[numtostr[u]];
		gang = u;
	}
	
	for(int i=0;i<cnt;i++){
		if(edge[i][u]){
			total += edge[i][u];
			edge[i][u] = edge[u][i] = 0;
			if(!f[i]){
				f[i] = true;
				groupnum++;
				DFS(i,gang,groupnum,total);
			}
		} 
	}
	
}
map<string,int> mp;

int main(){
	scanf("%d%d",&N,&K);

	for(int i=0;i<N;i++){
		string s1;
		string s2;
		int t;
		cin >> s1 >> s2 >> t;
		if(strtonum.find(s1)==strtonum.end()){
			strtonum[s1] = cnt;
			numtostr[cnt] = s1;
			cnt++;
		}
		if(strtonum.find(s2)==strtonum.end()){
			strtonum[s2] = cnt;
			numtostr[cnt] = s2;
			cnt++;
		}
		TotalFee[s1] += t;
		TotalFee[s2] += t;
		edge[strtonum[s1]][strtonum[s2]] += t;
		edge[strtonum[s2]][strtonum[s1]] += t;
	}
	
	for(int i=0;i<cnt;i++){
		int gang,groupnum = 1,totaledge = 0;
		maxn = -1;
		if(!f[i]){
			f[i] = true;
			DFS(i,gang,groupnum,totaledge);
			if(totaledge>K && groupnum>2){
				mp[numtostr[gang]] = groupnum;
			}
		}
	}
	int res = mp.size();
	printf("%d\n",res);
	for(auto it=mp.begin();it!=mp.end();it++){
		printf("%s %d\n",it->first.c_str(),it->second);
	}
	return 0; 
}

1035 Password (20 分)

算法标签: 字符串

#include<bits/stdc++.h>
using namespace std;
struct team{
	string name;
	string p;
};
team t[10005];
int main(){
	int M;
	scanf("%d",&M);
	int cnt = 0;
	for(int i=0;i<M;i++){
		string name;
		string password;
		cin >> name >> password;
		bool f = false;
		for(int j=0;j<password.size();j++){
			if(password[j] == '1'){
				password[j] = '@';
				f = true;
			}else if(password[j] == 'O'){
				password[j] = 'o';
				f = true;
			}else if(password[j] == 'l'){
				password[j] = 'L';
				f = true;
			}else if(password[j] =='0'){
				password[j] = '%';
				f = true;
			}
		}
		if(f){
			t[cnt].name = name;
			t[cnt++].p = password;
		}
		
	} 
	if(cnt){
		cout << cnt << endl;
		for(int i=0;i<cnt;i++){
			cout << t[i].name << " " << t[i].p << endl;
		}
	}else{
		if(M == 1){
			cout << "There is 1 account and no account is modified" << endl;
		}else{
			cout << "There are "<< M <<" accounts and no account is modified" << endl;
		}
	}
	return 0;
}

1036 Boys vs Girls (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;

int main(){
	int M;
	cin >> M;
	string m_name;
	string f_name;
	string m_course;
	string f_course;
	int m_score = 101;
	int f_score = -1;
	
	for(int i=0;i<M;i++){
		string s;
		cin >> s;
		string sex;
		cin >> sex;
		string course;
		cin >> course;
		int score;
		cin >> score;
		if(sex == "M"){
			if(score<=m_score){
				m_score = score;
				m_name = s;
				m_course = course;
			}
		}else{
			if(score >= f_score){
				f_score = score;
				f_name = s;
				f_course = course;
			}
		}
	}
	if(m_score == 101 && f_score == -1){
		cout << "Absent" << endl 
		<< "Absent" << endl 
		<< "NA" ;
	}else if(f_score == -1){
		cout << "Absent" << endl 
		<< m_name << " " << m_course  << endl << "NA";
	}else if(m_score == 101){
		cout << f_name << " " << f_course << endl 
		<< "Absent" << endl << "NA" ;
	}else{
		cout << f_name << " " << f_course <<   endl
		<< m_name << " " << m_course <<  endl << f_score-m_score;
	}
	return 0;
}

1037 Magic Coupon (25 分)

算法标签: 排序 + 贪心
注意点: 最大值一定是负数和负数相乘+正数和正数相乘,且两数相对差越小,乘积越大:
a ∗ b + c ∗ d > = a ∗ c + b ∗ d , a > = b > = c > = d a*b+c*d>=a*c+b*d,a>=b>=c>=d ab+cd>=ac+bd,a>=b>=c>=d

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int b[maxn];
long long sum = 0;

int main(){
	int NC,NP;
	scanf("%d",&NC);
	for(int i=0;i<NC;i++){
		scanf("%d",&a[i]);
	}
	scanf("%d",&NP);
	for(int i=0;i<NP;i++){
		scanf("%d",&b[i]);
	}
	sort(a,a+NC);
	sort(b,b+NP);
	for(int i=0,j=0;i<min(NC,NP);i++,j++){
		if(a[i]<0 && b[j]<0){
			sum += a[i] * b[j];
		}else{
			break;
		}
	}
	for(int i=NC-1,j=NP-1;i>=0 && j>=0;i--,j--){
		if(a[i]>0 && b[j]>0){
			sum += a[i]*b[j];
		}else{
			break;
		}
	}
	printf("%lld\n",sum); 
	return 0;
} 

1038 Recover the Smallest Number (30 分)

算法标签: 贪心 + 字符串
注意点: 生成字典序最小的字符串必须满足局部子式 s 1 s 2 < s 2 s 1 s_1s_2<s_2s_1 s1s2<s2s1

#include<bits/stdc++.h>
using namespace std;
string s[10005];

bool cmp(string s1,string s2){
	return s1+s2 < s2+s1;
}

int main(){
	int N;
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		cin >> s[i];
	}	
	sort(s,s+N,cmp);
	string ans = "";
	for(int i=0;i<N;i++){
		ans += s[i];
	}
	int len = ans.size();
	bool f = false;
	for(int i=0;i<len;i++){
		if(!f && ans[i]=='0'){
			continue;
		}else{
			f = true;
			printf("%c",ans[i]);
		}
	}
	if(!f){
		printf("0\n");
	}
	
	return 0;
} 

1039 Course List for Student (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
 
const int maxn = 26*26*26*10 + 5; 
vector<int> hashT[maxn];
int hash1(char s[]){
    int id = 0;
    for(int i=0;i<3;i++){
        id = id * 26 + s[i] - 'A';
    }
    id = id *10 + s[3]-'0';
    return id;
}
int main(){
    int N,K;
     
    cin.tie(0);
    cout.tie(0);
     
    scanf("%d%d",&N,&K);
        for(int i=0;i<K;i++){
            int index,n;
            scanf("%d%d",&index,&n);
            for(int j=0;j<n;j++){
                char s1[10];
                scanf("%s",s1);
                int id = hash1(s1);
                hashT[id].push_back(index);
            }
        }
        for(int i=0;i<N;i++){
            char s1[10];
            scanf("%s",s1);
            int id = hash1(s1);
            printf("%s %d",s1,hashT[id].size());
            sort(hashT[id].begin(),hashT[id].end());
            vector<int>::iterator it;
            for(it = hashT[id].begin();it!=hashT[id].end();it++){
                printf(" %d",*it);
            }
            printf("\n");
        }
     
    return 0;
} 

1040 Longest Symmetric String (25 分)

算法标签: DP
注意点: 动态规划求最长回文子串的题目,可得初始条件如下:
d p [ i ] [ j ] dp[i][j] dp[i][j]表示从第i个字符到第j个字符为回文串,那么
d p [ i ] [ i ] = 1 , L = 1 dp[i][i]=1,L=1 dp[i][i]=1,L=1
d p [ i ] [ i + 1 ] = 1 , s [ i ] = = s [ i + 1 ] , L = 2 dp[i][i+1]=1,s[i]==s[i+1],L=2 dp[i][i+1]=1,s[i]==s[i+1],L=2
d p [ i ] [ j ] = 1 , d p [ i + 1 ] [ j − 1 ] = 1 且 s [ i ] = = s [ j ] , L > = 3 dp[i][j]=1,dp[i+1][j-1]=1且s[i]==s[j],L>=3 dp[i][j]=1,dp[i+1][j1]=1s[i]==s[j],L>=3

#include<bits/stdc++.h>
using namespace std;
int dp[1005][1005];

int main(){
	string s;
	getline(cin,s);
	int len = s.size();
	int ans = 1;
	for(int i=0;i<len;i++){
		dp[i][i] = 1;
		if(i>=1 && s[i-1]==s[i]){
			dp[i-1][i] = 1;
			ans = 2;
		}
	}
	
	for(int i=3;i<=len;i++){
		for(int j=0;j<len-i+1;j++){
			int k = j+i-1;
			if(s[k] == s[j] && dp[j+1][k-1]==1){
				dp[j][k] = 1;
				ans = i;
			}
		}
	}
	cout << ans << endl;
	return 0; 
}

1041 Be Unique (20 分)

算法标签: 哈希

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int hashT[10005];

int main(){
	int N;
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		scanf("%d",&a[i]);
		hashT[a[i]] ++;
	}
	for(int i=0;i<N;i++){
		if(hashT[a[i]]==1){
			printf("%d\n",a[i]);
			return 0;
		}
	}
	printf("None\n");
	
	return 0;
} 

1042 Shuffling Machine (20 分)

算法标签: 模拟
注意点: 模拟混洗序列,核心公式为 c [ b [ j ] ] = a [ j ] ; c[b[j]] = a[j]; c[b[j]]=a[j];

#include<bits/stdc++.h>
using namespace std;
int a[105];
int b[105];
int c[105];
string s = "SHCDJ";

int main(){
	int K;
	cin >> K;
	
	for(int i=1;i<=54;i++){
		a[i] = i;
	}
	
	for(int i=1;i<=54;i++){
		cin >> b[i];
	}
	
	for(int i=1;i<=K;i++){
		for(int j=1;j<=54;j++){
			c[b[j]] = a[j];
		}
		for(int j=1;j<=54;j++){
			a[j] = c[j];
		}
	}
	
	for(int i=1;i<=54;i++){
		cout << s[(a[i]-1)/13];
		cout << (a[i]-1) % 13 + 1;
		if(i!=54){
			cout << " ";
		}else{
			cout << endl;
		}
	}
	
	return 0;
	
} 

1043 Is It a Binary Search Tree (25 分)

算法标签: 树,二叉树 + 遍历
注意点: 所谓的镜像树,其实就是指颠倒了左右子树的访问顺序,其它条件都不变,因此,本题实质上依然是考察建树+遍历

#include<bits/stdc++.h>
using namespace std;

vector<int> pre,preM,post,postM,origin;

int N; 
struct node{
	int data;
	node* lchild;
	node* rchild;
};

node* root = NULL;

void insert(node* &root,int x){
	if(root==NULL){
		node *Node = new node;
		Node->data = x;
		Node->lchild = NULL;
		Node->rchild = NULL;
		root = Node;
		return;
	}
	if(x<root->data){
		insert(root->lchild,x);
	}else{
		insert(root->rchild,x);
	}
}

int cnt = 0;

void PreOrder(node* root,vector<int> &pre){
	if(root==NULL){
		return;
	}
	pre.push_back(root->data);
	PreOrder(root->lchild,pre);
	PreOrder(root->rchild,pre);
}

void MirrorOrder(node *root,vector<int> &preM){
	if(root==NULL){
		return;
	}
	preM.push_back(root->data);
	MirrorOrder(root->rchild,preM);
	MirrorOrder(root->lchild,preM);
}

void PostOrder(node* root,vector<int> &post){
	if(root==NULL){
		return;
	}
	PostOrder(root->lchild,post);
	PostOrder(root->rchild,post);
	post.push_back(root->data);
}

void PostOrder1(node* root,vector<int> &postM){
	if(root==NULL){
		return;
	}
	PostOrder1(root->rchild,postM);
	PostOrder1(root->lchild,postM);
	postM.push_back(root->data);
}

int main(){
	cin >> N;
	for(int i=0;i<N;i++){
		int t;
		cin >> t;
		origin.push_back(t);
		insert(root,t);
	}
	
	PreOrder(root,pre);
	MirrorOrder(root,preM);
	
	if(pre==origin){
		printf("YES\n");
		PostOrder(root,post);
		for(int i=0;i<post.size();i++){
			if(i==0){
				printf("%d",post[i]);
			}else{
				printf(" %d",post[i]);
			}
		}
	}else if(preM==origin){
		printf("YES\n");
		PostOrder1(root,postM);
		for(int i=0;i<postM.size();i++){
			if(i==0){
				printf("%d",postM[i]);
			}else{
				printf(" %d",postM[i]);
			}
		}
	}else{
		printf("NO\n");
	}
	
	return 0;
}

1044 Shopping in Mars (25 分)

算法标签: 模拟 + 二分
注意点: 先二分求最小间距,然后二分遍历求数对 ( a , b ) (a,b) (a,b)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int sum[maxn];
int main(){
	int N,M;
	scanf("%d%d",&N,&M);
	for(int i=1;i<=N;i++){
		scanf("%d",&a[i]);
		sum[i] = sum[i-1] + a[i];
	}
	
	int minS =INT_MAX;
	for(int i=1;i<=N;i++){
		int pos = upper_bound(sum+1,sum+N+1,sum[i-1]+M)-sum;
		if(sum[pos-1]-sum[i-1]==M){
			minS = M;
			break;
		}else if(sum[pos]-sum[i-1]>M){
			minS = min(minS,sum[pos]-sum[i-1]);
		}
	}
	
	for(int i=1;i<=N;i++){
		int pos = upper_bound(sum+1,sum+N+1,sum[i-1]+minS)-sum;
		if(sum[pos-1]-sum[i-1]==minS){
			printf("%d-%d\n",i,pos-1);
		}
	}
	return 0;
};

1045 Favorite Color Stripe (30 分)

算法标签: DP
注意点: 最长不降子序列(LIS),状态转移方程为:
d p [ j ] = m a x ( d p [ j ] , d p [ i ] + 1 ) , i < j dp[j]=max(dp[j],dp[i]+1),i<j dp[j]=max(dp[j],dp[i]+1),i<j

#include<bits/stdc++.h>
using namespace std;

bool flag[205];
int hashT[205];
int a[10005];
int dp[10005];

int main(){
	int N;
	scanf("%d",&N);
	int M;
	scanf("%d",&M);
	for(int i=0;i<M;i++){
		int t;
		scanf("%d",&t);
		if(!flag[t]){
			hashT[t] = i;
			flag[t] = true;
		}
	}
	
	int L;
	scanf("%d",&L);
	int cnt = 0;
	for(int i=0;i<L;i++){
		int t;
		scanf("%d",&t);
		if(flag[t]){
			a[cnt++] = t;
		}
	}

	for(int i=0;i<cnt;i++){
		dp[i] = 1;
		for(int j=0;j<i;j++){
			if(hashT[a[j]] <= hashT[a[i]]){
				dp[i] = max(dp[i],dp[j]+1);
			}
		}
	}
	int maxn = -1;
	for(int i=0;i<cnt;i++){
		maxn = max(maxn,dp[i]);
	}
	cout << maxn << endl;
	return 0;
} 

1046 Shortest Distance (20 分)

算法标签: 模拟 + 前缀和
注意点: 求前缀和数组(预处理),查询输出

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int sum[maxn];

int main(){
	int N;
	cin >> N;
	for(int i=1;i<=N;i++){
		cin >> a[i];
		sum[i] = sum[i-1] + a[i];
	}
	int cnt = sum[N];
	int M;
	cin >> M;
	for(int i=1;i<=M;i++){
		int s1,s2;
		cin >> s1 >> s2;
		if(s1>s2){
			swap(s1,s2);
		}
		int res;
		res = min(sum[s2-1]-sum[s1-1],cnt-(sum[s2-1]-sum[s1-1]));
		cout << res << endl;
	}
	return 0;
} 

1047 Student List for Course (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
 
vector<int> hashT[2505];
int hash1(char s[]){
    int id = 0;
    for(int i=0;i<3;i++){
        id = id * 26 + s[i] -'A';
    }
    id = id * 10 + s[3] -'0';
    return id;
}
char s2[10];
 
void rhash(int id,char s[]){
    s[3] = id % 10 + '0';
    id/=10;
    int j = 2;
    while(j+1){
        s[j--] = id % 26+ 'A';
        id /= 26;
    }
    s[4] = '\0';
}
int main(){
    int N,K;
    scanf("%d%d",&N,&K);
    for(int i=0;i<N;i++){
        char s1[10];
        scanf("%s",s1);
        int id = hash1(s1);
        int t;
        scanf("%d",&t);
        for(int j=0;j<t;j++){
            int p;
            scanf("%d",&p);
            hashT[p].push_back(id);
        }
    }
    for(int i=1;i<=K;i++){
        printf("%d %d\n",i,hashT[i].size());
        vector<int>::iterator it;
        sort(hashT[i].begin(),hashT[i].end());
        for(it = hashT[i].begin();it!=hashT[i].end();it++){
            rhash(*it,s2);
            printf("%s\n",s2);
        }
    }
    return 0;
} 

1048 Find Coins (25 分)

算法标签: 哈希 + two pointers
注意点: 双指针问题,从前到后枚举每个数,考察其和为M的另一个数是否存在,是就输出结果,注意特判两数相等的情形

#include<bits/stdc++.h>
using namespace std;
int a[10005];

int main(){
	int N,M;
	scanf("%d%d",&N,&M);
	for(int i=0;i<N;i++){
		int t;
		scanf("%d",&t);
		a[t]++;
	}
	for(int i=0;i<=M/2;i++){
		if(i == M/2 && 2*i==M){
			if(a[i]>=2){
				printf("%d %d\n",i,M-i);
				return 0;
			}
		}else{
			if(a[i]>=1 && a[M-i]>=1){
				printf("%d %d\n",i,M-i);
				return 0;
			}
		}
	}
	printf("No Solution\n");
	return 0;
} 

1049 Counting Ones (30 分)

算法标签: 数论
注意点: 一道好题!求1的数量,我们可以将数字分成3个部分,左中右,中间的是当前正在处理的数字,可分为3类: < 1 ∣ = 1 ∣ > 1 <1|=1|>1 <1=1>1
1. = 0 ( < 1 ) : a n s + = l e f t ∗ a =0(<1):ans+=left*a =0(<1):ans+=lefta
2. = 1 : a n s + = l e f t ∗ a + r i g h t + 1 =1:ans+=left*a+right+1 =1:ans+=lefta+right+1
3. > 1 : a n s + = ( l e f t + 1 ) ∗ a >1:ans+=(left+1)*a >1:ans+=(left+1)a

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n;
	scanf("%d",&n);
	int n1 = n;
	int cnt = 0;
	while(n1){
		n1/=10;
		cnt++;
	}
	int p = 1;
	long long sum = 0;
	for(int i=0;i<cnt;i++){
		int left = n/p/10;
		int now = n/p%10;
		int right = n%p;
		if(now==0){
			sum += (left*p);
		}else if(now==1){
			sum += (left*p + right +1);
		}else{
			sum += (left+1)*p;
		}
		p*=10;
	}
	printf("%lld\n",sum);
	
	return 0;
}

1050 String Subtraction (20 分)

算法标签: 字符串

#include<stdio.h>
#include<string.h>
#include<stdbool.h>
bool hashT[256];
char s1[10005];
char s2[10005];
int main(){
	gets(s1);
	gets(s2);
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	for(int i=0;i<len2;i++){
		hashT[s2[i]] = true;
	}
	for(int i=0;i<len1;i++){
		if(!hashT[s1[i]]){
			printf("%c",s1[i]);
		}
	} 
	printf("\n");
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值