GPLT模拟赛总结

GPLT模拟赛总结~

比赛的时候写的心态爆炸 掀桌 其实比完看看还是有不少模板题的QWQ
原题链接
7-2 小明环游宇宙 (5分)
进制转换。借助十进制作为中间变量进行转换。题目说了都是小于10进制的数~基础题。

#include
#include
#include
using namespace std;

int a,b,temp;
char c[1005];
stack<int> s;

int convert_to_10(int a, char* c){
	int ans = 0, len = strlen(c);
	for(int i = 0; i < len; ++i)
		ans = ans * a + c[i] - '0';
	return ans;
}
void convert_to_b(int temp, int b){
	do{
		s.push(temp % b); 
	}while(temp /= b);
	while(s.size()){
		printf("%d",s.top());
		s.pop();
	}
}
int main(){
	scanf("%d%d %s",&a,&b,c);
	temp = convert_to_10(a,c);
	convert_to_b(temp, b);
	return 0;
} 

放一个通用的(可以>10)的代码:

#include 
#include 
#include
int convert(int n,char *a){
	int len = strlen(a);
	int ans = 0;
	for(int i = 0;i < len; i++){
		if(isdigit(a[i]))
			ans = ans * n + a[i] - '0';
		else
			ans = ans * n + a[i] - 'A' + 10;
	}	
	return ans;
}
void conv(int ans,int b){
	char arr[1005];
	int cnt = 0,tmp;
	while(ans){
		tmp = ans % b;
		if(tmp >= 10)
			arr[cnt++] = tmp - 10 + 'A';
		else
			arr[cnt++] = tmp + '0';
		ans = ans / b;
	}
	for(int i = cnt - 1; i >= 0; i--)
		printf("%c",arr[i]);
}
int main(){
	char a[1005];
	int n, b, temp;
	scanf("%d%d%s",&n,&b,a);
	temp = convert(n,a); 
	conv(temp,b);
	return 0;
}

7-3 纸条 (10分)
基础题~strstr(第二个参数才是要查找的子串!)的应用!
用两个指针移动就可以啦 用最简单的方法就好。注意字符串是const char*,不能移动哦~

#include
#include

char target[] = "19260817", str[1000005], *p, *q;
int cnt;
int main(){
	scanf("%s",str);
	q = str;
	while(p = strstr(q,target)){
		cnt++;
		q = p + 1;
	}
	printf("%d",cnt);
	return 0;
}


7-4 争一 (10分)
我不想再看见这个题了……就因为开这个又没注意细节,后面都没时间了 血亏!
“首先按照得分高低排名,如果有人得分相同,那么最初位置是东的排在南、西、北的前面,南排在西、北前面,西排在北前面。”

#include
#include
using namespace std;

bool judgenorth(int a, int b, int c, int d){
	int large = max(max(a,b),c);
	//stage 1
	if(d + 12000 > large - 4000)	return true;
	//stage 2
	d += 12000;
	if((d > a - 12000 && d > b && d > c) || (d > b - 12000 && d > a && d > c) || (d > c - 12000 && d > a && d > b))	return true;
	return false;
}
bool judgeeast(int a,int b,int c,int d){			
	//stage 3
	if((a + 8000) >= max(max(b - 2000, c - 2000), d - 4000))	return true;
	//stage 4
	a += 8000;
	if((a >= b - 8000 && a >= c && a >= d) || (a >= c - 8000 && a >= b && a >= d) || (a >= d - 8000 && a >= c && a >= b))	return true;
	return false;
}
bool judgesouth(int a,int b,int c,int d){			  
	//stage 3
	if((b + 8000) >= max(c - 2000, d - 4000) && (b + 8000) > a - 2000)	return true;
	//stage 4
	b += 8000;
	if((b > a - 8000 && b >= c && b >= d) || (b >= c - 8000 && b > a && b >= d) || (b >= d - 8000 && b >= c && b > a))	return true;
	return false;
}
bool judgewest(int a,int b,int c,int d){			 
	//stage 3
	if((c + 8000) > max(a - 2000, b - 2000) && c + 8000 >= d - 4000)	return true;
	//stage 4
	c += 8000;
	if((c > a - 8000 && c > b && c >= d) || (c > b - 8000 && c > a && c >= d) || (c >= d - 8000 && c > b && c > a))	return true;
	return false;
}
int main(){
	int n,a,b,c,d;
	scanf("%d",&n);
	for(int i = 1; i <= n; ++i){
		scanf("%d%d%d%d",&a,&b,&c,&d);
		(judgeeast(a,b,c,d))?	printf("1 ") : printf("0 ");
		(judgesouth(a,b,c,d))?	printf("1 ") : printf("0 ");
		(judgewest(a,b,c,d))?	printf("1 ") : printf("0 ");
		(judgenorth(a,b,c,d))?	printf("1 ") : printf("0 ");
		printf("\n");
	}
	return 0;
}

7-5 王者荣耀 (15分)
简单题。根据题意模拟就好~不要被吓到,其实很简单的!

#include

int n,x1,y1;

int main(){
	scanf("%d",&n);
	for(int i = 1; i <= n; ++i){
		scanf("%d%d",&x1,&y1);
		if(i <= 3 || ((i - 3) % 4 == 0)){
			printf("%d %d %d\n",x1 + 1,y1,3);
		}else{
			if(i % 4 == 0)	printf("%d %d %d\n",x1 + 1,y1,3);
			if((i - 1) % 4 == 0)	printf("%d %d %d\n",x1 - 1,y1,1);
			if((i - 2) % 4 == 0)	printf("%d %d %d\n",x1 + 1,y1,3);
		}
	}
	return 0;
}

7-6 不管是谁都最喜欢 (15分)
map的应用。注意是结尾等于!所以要用substr截断;再者坑点是重复输出,用map去重~

#include
#include
#include
#include
#include
using namespace std;

map<string, bool> mp;
vector<string> VTUBER;
vector<string> DD;
int a;
string s, buff, s1 = "_official", s2 = "_0fficial", s3 = "_officiaI", s4 = "_0fficiaI";

int main(){
	scanf("%d",&a);
	while(cin >> s){
		int len = s.length();
		if(len >= 9){
			buff = s.substr(len - 9);
			if(!mp.count(s) && buff == s1){
				VTUBER.push_back(s);
				mp[s] = true; 
			}else if(!mp.count(s) && (buff == s2 || buff == s3 || buff == s4)){
				DD.push_back(s);
				mp[s] = true; 
			}
		} 
	}
	printf("%d %d\n",VTUBER.size(), DD.size());
	for(int i = 0; i < VTUBER.size(); ++i)
		cout << VTUBER[i] << endl;
	for(int i = 0; i < DD.size(); ++i)
		cout << DD[i] << endl;
	return 0;
}

7-7 代码统计 (20分)
这不是PAT的题嘛QWQ 柱状图输出字母统计~注意输出格式 行末空格的问题!

#include
#include
#include

int book[30],maxx;
char c;

int main(){
	while((c = getchar()) != EOF){
		if(isalpha(c)){
			book[toupper(c) - 'A' + 1]++;
			if(maxx < book[toupper(c) - 'A' + 1])	maxx = book[toupper(c) - 'A' + 1];
		}
	}
	for(int i = maxx; i >= 1; --i){
		for(int j = 1; j <= 26; ++j){
			if(j != 26){
				if(book[j] >= i){
					printf("* ");
					book[j]--;
				}else	printf("  ");
			}else{
				if(book[j] >= i){
					printf("*");
					book[j]--;
				}else	printf(" ");
			}
		
		}
		putchar('\n');
	}
	for(int i = 0; i < 26; ++i)
		(i == 25) ? printf("%c",'A' + i) : printf("%c ",'A' + i);
	return 0;
}

7-11 动物王国 (25分)
模拟就好啦……根据题意写~

#include
#include
using namespace std;

int n,q,x,y;
int fa[100005],cake[100005];

void solve(int x, int y){
	int start = x, end = y;
	while(start != end){
		cake[start]++;
		start = fa[start];
	}
}
int main(){
	scanf("%d%d",&n,&q);
	for(int i = 1; i <= n; ++i){
		scanf("%d",&fa[i]);		//被管理 
	}
	for(int i = 1; i <= q; ++i){
		scanf("%d%d",&x,&y);
		solve(x,y);
	}	
	for(int i = 1; i <= n; ++i)
		(i == 1) ? printf("%d",cake[i]) : printf(" %d",cake[i]);
	return 0;
}
 

7-12 传话的难度 (25分)
标准的mst(最小生成树)算法。个人习惯使用kruskal。注意一点就是求的是最大的传话难度,不是总的难度~

#include
#include
using namespace std;
const int maxn = 200005;

int n,m,f[maxn],ans,cnt;
struct node{
	int u,v,w;
}book[maxn];
int cmp(node n1, node n2){return n1.w < n2.w;}

int find(int x){return f[x] == x ? x : f[x] = find(f[x]);}
int unite(int x, int y){
	int fa = find(x), fb = find(y);
	if(fa == fb)	return 0;
	else	f[fb] = f[fa];
	return 1;
} 
void init(){
	for(int i = 1; i <= n; ++i)	f[i] = i;
	cnt = 0;
}

int main(){
	scanf("%d%d",&n,&m);
	init();
	for(int i = 1; i <= m; ++i)
		scanf("%d%d%d",&book[i].u,&book[i].v,&book[i].w);
	sort(book + 1, book + 1 + m, cmp);
	//kruskal
	int i;
	for(i = 1; i <= m; ++i){
		if(unite(book[i].u, book[i].v))
			cnt++;				//只要看最大的,这里不用统计~
		if(cnt == n - 1){
			ans = book[i].w;
			break;
		}
	}
	printf("%d",ans);
	return 0;
} 

顺便复习一下并查集的模板/Kruskal的模板~
并查集(简单的版本):

void init(){
	for(int i = 1; i <= n; ++i)
		f[i] = i;
}
int find(x){return f[x] == x ? x : f[x] = find(f[x]);}
void unite(int x,int y){f[find(y)] = f[find(x)];}
bool check(int x, int y){return find(x) == find(y);} 

Kruskal核心代码:

int unite(int x,int y){		//并(和一般并查集不太一样)
	int r1 = find(x),r2 = find(y);
	if(r1 == r2) return 0;	
	else{
		f[r2] = f[r1];
		return 1;
	}
}

for(int i = 0; i < m; ++i){			//m是边数
		if(unite(city[i].u, city[i].v)){
			ans += city[i].w;		//计算总边权
			cnt++;
		}else	continue;
		if(cnt == n - 1)
			break;
	}

未完待续~

你可能感兴趣的:(acm竞赛,算法)