PTA刷题日记10

1091 Acute Stroke (30 分)

数三维数组的连通块,并计算块大小大于等于t的体积之和
dfs和bfs都写了,但是dfs会爆栈的,所以迷宫类问题还是bfs吧,时间复杂度应该差不多

#include<bits/stdc++.h> 
using namespace std;
bool matrix[1300][130][65], vis[1300][130][65];
int X[8] = {0, 0, 1, -1, 0, 0};
int Y[8] = {1, -1, 0, 0, 0, 0};
int Z[8] = {0, 0, 0, 0, -1, 1};
int m, n, l, t;
//三维数组的bfs和dfs,应该会都写一下 
struct node{
	int x, y, z;
};

bool judge(int x, int y, int z) {
	if(x < 0 || x > m-1 || y < 0 || z < 0 || y > n-1 || z > l-1) return false;
	if(vis[x][y][z] || !matrix[x][y][z]) return false;
	return true;
}

int dfs(int x, int y, int z) {
	vis[x][y][z] = 1;
	int vol = 1;
	for(int i = 0; i < 6; i++) {//6个方向 
		int nx = x + X[i], ny = y + Y[i], nz = z + Z[i];
		if(judge(nx, ny, nz)){
			vol += dfs(nx, ny, nz);
		}
	}
	return vol;
}

int bfs(int x, int y, int z) {
	queue<node> q;
	node s = {x,y,z};
	q.push(s);
	vis[x][y][z] = 1;
	int vol = 1;
	while(q.size()) {
		node now = q.front();
		q.pop();
		for(int i = 0; i < 6; i++) {//6个方向 
			int nx = now.x + X[i], ny = now.y + Y[i], nz = now.z + Z[i];
			if(judge(nx, ny, nz)){
				vol ++;
				vis[nx][ny][nz] = 1;
				q.push({nx, ny, nz});
			}
		}	
	}
	return vol;
}

int main() {
	scanf("%d %d %d %d",&m,&n,&l,&t);
	//m行n列k层 
	for(int k = 0; k < l; k++) {
		for(int i = 0; i < m; i++) {
			for(int j = 0; j < n; j++) {
				scanf("%d",&matrix[i][j][k]);
			}
		}
	}
	int total = 0;
	for(int k = 0; k < l; k++) {
		for(int i = 0; i < m; i++) {
			for(int j = 0; j < n; j++) {
				if(!vis[i][j][k] && matrix[i][j][k]) {
					int tem = bfs(i, j, k);
					if(tem >= t)total += tem;
				}
			}
			
		}
	}
	printf("%d\n",total);
	return 0;
}

1092 To Buy or Not to Buy (20 分)

记录第二个串中的字母是否都在第一个串中出现(数量需考虑)

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

int main() {
	string a, b;
	cin >> a >> b;
	for(int i = 0; i < a.length(); i++) {
		cnt[a[i]]++;
	}
	int l = b.length(), sh = 0;
	for(int i = 0; i < b.length(); i++) {
		if(cnt[b[i]] > 0) cnt[b[i]]--, l--;
		else {
			sh++;
		}
	} 
	if(l) printf("No %d",sh);
	else printf("Yes %d",a.length() - b.length());
	return 0;
} 

1093 Count PAT’s (25 分)

遍历一遍字符串,记录A的位置,和初始位置到每个位置上P和T的数量,然后遍历一遍A的位置,每次答案加上A前面P的个数*后面T的数量

#include<bits/stdc++.h> 
using namespace std;
const int N = 1e5 + 5;
const int mod = 1e9 + 7;
int pnum[N], tnum[N];
vector<int> pos;
#define ll long long

int  main() {
	char ch;
	int p = 0;
	while(cin >> ch) {
		pnum[++p] = pnum[p-1];
		tnum[p] = tnum[p-1];
		if(ch == 'P') pnum[p]++;
		else if(ch == 'A') pos.push_back(p);
		else if(ch == 'T') tnum[p] ++;
	}
	ll ans = 0;
	for(int i = 0; i < pos.size(); i++) {
		int j = pos[i];
		ans = (ans + pnum[j] * (tnum[p] - tnum[j])) % mod;
	}
	cout<<ans<<endl;
	return 0;
} 

1094 The Largest Generation (25 分)

bfs,dfs都可以,数据量很小无所谓,找结点数最多的一层,并输出数量和所在层

#include<bits/stdc++.h>
using namespace std;
vector<int> v[105];
int num[105], depth[105], ma, gene;

void dfs(int x) {
	for(int i = 0; i < v[x].size(); i++) {
		int y = v[x][i];
		depth[y] = depth[x] + 1;
		num[depth[y]]++;
		if(num[depth[y]] > ma) {
			ma = num[depth[y]];
			gene = depth[y];
		}
		dfs(y);
	}
}

int main() {
	int n, m, p, k, kid;
	scanf("%d %d",&n, &m);
	for(int i = 0; i < m; i++) {
		scanf("%d %d",&p, &k);
		while(k--) {
			scanf("%d",&kid);
			v[p].push_back(kid);
		}
	}
	ma = depth[1] = 1;
	gene = num[1] = 1;
	dfs(1);
	printf("%d %d",ma, gene);
	return 0;
}
/*
23 13
21 1 23
01 4 03 02 04 05
03 3 06 07 08
06 2 12 13
13 1 21
08 2 15 16
02 2 09 10
11 2 19 20
17 1 22
05 1 11
07 1 14
09 1 17
10 1 18

3 1
1 2 2 3
*/

1095 Cars on Campus (30 分)

这道题前面有个类似的去银行处理事务的题,但是这题感觉更复杂,因为有一个查询

查询处理

这个查询显然线性查应该是会超时的(没试,我也不知道),所以用了内置的upper_bound函数进行二分查找,就是把合法的时间段(in和out成功配对)分别加入一个in数组,一个out数组,(我做了个简单测试,应该还是数组排序更快,但这里用vector也没有超时,应该数据量不算太大)然后分别查找到现在时间所在的位置,已经进去的车的数量-已经出来的车的数量=当前停车数

vector和数组的测试

#include<bits/stdc++.h>
using namespace std;
const int N = 5e6 + 5;
int arr[N];
vector<int> a;

int main()
{
    int n = 5e6;
    mt19937 rand_num(unsigned(time(0))); 
	uniform_int_distribution<long long> dist(1, 1000000); 
    for(int i = 0; i < n; i++) {
    	int t = dist(rand_num);
    	arr[i] = t;
    	a.push_back(t);
	}
	clock_t st1, st2, ed1, ed2;
	st1 = clock();
	sort(arr, arr+n);
	ed1 = clock();
	st2 = clock();
	sort(a.begin(), a.end());
	ed2 = clock();
	cout<< "Run1: "<<(int)(ed1-st1)*1000 / CLOCKS_PER_SEC << "ms" <<endl;
	cout<< "Run2: "<<(int)(ed2-st2)*1000 / CLOCKS_PER_SEC << "ms" <<endl;
    return 0;
}

在这里插入图片描述

其他处理

1.时间读入的时候可以根据格式直接读入时分秒,然后全部转换成秒,后面处理起来也会更方便
2.注意是否合法数据的处理,遇到in直接向后即可,遇到out判断前面是不是in,是in才是合法的,其他情况都不合法

#include<bits/stdc++.h>
using namespace std;
struct record{
	int time;
	bool f;
	friend bool operator< (record a, record b) {
		return a.time < b.time;
	}
};
unordered_map<string, vector<record> >mp;
unordered_map<string, int> per;
set<string> name;
vector<int> in, out;

int cal(int h, int m, int s){
	return 3600*h + 60*m + s;
}

int main() {
	int n, k, h, m, s, maxt = -1;
	scanf("%d %d",&n,&k);
	string a,b;
	a.resize(7);
	b.resize(2);
	record r;
	for(int i = 0; i < n; i++) {
		scanf("%s %2d:%2d:%2d %s",&a[0],&h,&m,&s,&b[0]);
		r.time = cal(h, m, s);
		if(b == "in") r.f = 0;
		else r.f = 1;
//		printf("%s %02d:%02d:%02d %d\n",a.c_str(),r.h,r.m,r.s,r.f);
		mp[a].push_back(r);
	}
	for(auto it: mp) {
		a = it.first;
		sort(mp[a].begin(), mp[a].end());
		int l = mp[a].size();
		r.f = 1;
		for(int i = 0; i < l; i++) {
			if(mp[a][i].f == 1) {//遇到out判断是不是合法数据 
				if(r.f == 0) {//配上了 
					in.push_back(r.time);
					out.push_back(mp[a][i].time);
					int pt = mp[a][i].time - r.time;
					per[a] += pt;
					if(maxt < per[a]) {
						maxt = per[a];
						name.clear();
						name.insert(a);
					}
					else if(maxt == per[a]) {
						name.insert(a);
					}
				}
			}
			r = mp[a][i];//遇到in直接向下 
		}	
	}
	sort(in.begin(), in.end());
	sort(out.begin(), out.end());
	for(int i = 0; i < k; i++) {
		scanf("%2d:%2d:%2d",&h,&m,&s);
		int nowt = cal(h, m, s);
		int p1 = upper_bound(in.begin(), in.end(), nowt) - in.begin();
		int p2 = upper_bound(out.begin(), out.end(), nowt) - out.begin();
		printf("%d\n",p1-p2);
	}
	for(auto it: name) {
		cout<<it<<" ";
	}
	h = maxt/3600;
	m = (maxt%3600) / 60;
	s = (maxt%3600) % 60;
	printf("%02d:%02d:%02d\n",h,m,s);
	return 0;
}

1096 Consecutive Factors (20 分)

一开始我的写法是下面这种,肯定是错的很离谱啊,但是也有18分。。。。比如6720明明答案应该是{4,5,6,7,8}但是我试过{2,3,4,5}之后不会再回头了就会出现错误,所以必须还是得用循环嵌套的,一次遍历得答案是不可能的
还有最后两个测试点是质数,比如2,2147483647这种,质数也处理正确即可

for(int i = 2; i <= sqrt(n); i++ ) {
		if(t % i) {
			if(tnum > num) {
				num = tnum;
				ans = tem;
			}
			tem.clear();
			tnum = 0;
			t = n;
		}
		else {
			tnum++;
			t /= i;
			tem.push_back(i);
		}
	}
#include<bits/stdc++.h>
using namespace std;

int main() {
	int n, t, x, tnum = 0, num = 0, st;
	scanf("%d",&n);
	for(int i = 2; i <= sqrt(n)+1; i++ ) {
		x = i;
		t = n;
		tnum = 0;
		while(t % x == 0)  {
			tnum++;
			t /= x;
			x++;
		}
		if(tnum > num) {
			num = tnum;
			st = i;
		}
	}
    if(num == 0) {
    	printf("1\n%d",n);
	}
	else {
		cout<<num<<endl;
		for(int i = 0; i < num; i++) {
			if(i) printf("*");
			printf("%d",i + st);
		}	
	}
	
	return 0;
}

1097 Deduplication on a Linked List (25 分)

这题测试点2的坑在于给定的链表中没有需要删除的元素

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int L1[N], L2[N], val[N], nxt[N];
bool v[N];

int main() {
	int head, n, th, tn, t;
	scanf("%d %d",&head, &n);
	for(int i = 0; i < n; i++) {
		scanf("%d %d %d",&th, &t, &tn);
		nxt[th] = tn;
		val[th] = t;
	}
	int now = head, p = 0, q = 0; 
	for(int i = 0; i < n; i++) {
		if(now == -1) break;
		int data = abs(val[now]);
		if(v[data]) L2[q++] = now;//已经访问过了 
		else L1[p++] = now, v[data] = 1;
		now = nxt[now];
	}
	for(int i = 0; i < p-1; i++) {
		printf("%05d %d %05d\n", L1[i], val[L1[i]], L1[i+1]);
	}
	if(p) printf("%05d %d -1\n", L1[p-1], val[L1[p-1]]);
	for(int i = 0; i < q-1; i++) {
		printf("%05d %d %05d\n", L2[i], val[L2[i]], L2[i+1]);
	}
	if(q) printf("%05d %d -1\n", L2[q-1], val[L2[q-1]]);
	return 0;
}

1098 Insertion or Heap Sort (25 分)

1089和1098这两题可以充分背一下归并排序和堆排序

#include<bits/stdc++.h>
using namespace std;
int ori[105], des[105], n;

bool check() {
	for(int i = 0; i < n; i++) {
		if(ori[i+1] != des[i]) return false;
	}
	return true;
}

void shift_down(int i, int n) {
	while(i*2 <= n) {
		i *= 2;
		if(i+1 <= n && ori[i] < ori[i+1]) i++;
		if(ori[i] > ori[i/2]) swap(ori[i], ori[i/2]);
		else return;
	}
}

void create() {
	for(int i = n/2; i >= 1; i--) {
		shift_down(i, n);
	}
}

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", ori+i);
	for(int i = 0; i < n; i++) scanf("%d", des+i);
	bool f = 0;
	create();
	for(int i = n; i > 1; i--) {
		swap(ori[i], ori[1]);
		shift_down(1, i-1);
		if(f) {
			printf("Heap Sort\n");
			for(int i = 1; i <= n; i++) {
				if(i != 1) printf(" ");
				printf("%d", ori[i]);
			}
			return 0;
		}
		if(check()) f = 1;
	}
	printf("Insertion Sort\n");
	for(int i = 1; i < n; i++) {
		if(des[i] < des[i-1]) {
			int tem = des[i], j = i;
			for(; des[j-1] > tem; j-- ) {
				des[j] = des[j-1];
			}
			des[j] = tem;
			break;
		}
	}
	for(int i = 0; i < n; i++) {
		if(i) printf(" ");
		printf("%d",des[i]);
	}
	return 0;
}

1099 Build A Binary Search Tree (30 分)

首先给定树的结构,然后给一个序列,对BST进行中序遍历的结果就是一个有序的序列,所以对前面给定的序列排序之后,中序遍历一遍把所有元素赋上值,再层次遍历一遍即可

#include<bits/stdc++.h>
using namespace std;
int arr[105], cnt;
vector<int> ans;
struct node{
	int val, l, r;
}v[105];

void inorder(int root) {
	if(root == -1) return;
	inorder(v[root].l);
	v[root].val = arr[cnt++];
	inorder(v[root].r);
}

void levelorder() {
	queue<node> q;
	q.push(v[0]);
	while(q.size()) {
		node now = q.front();
		q.pop();
		ans.push_back(now.val);
		if(now.l != -1) q.push(v[now.l]);
		if(now.r != -1) q.push(v[now.r]);
	}
}


int main() {
	int n, l, r;
	scanf("%d",&n);
	for(int i = 0; i < n; i++) {
		scanf("%d %d",&l,&r);
		v[i].l = l, v[i].r = r;
	}
	for(int i = 0; i < n; i++) scanf("%d",arr+i);
	sort(arr, arr+n);//中序 
	inorder(0);
	levelorder();
	for(int i = 0; i < ans.size(); i++) {
		if(i) printf(" ");
		printf("%d",ans[i]);
	}
	return 0;
}

1100 Mars Numbers (20 分)

一个奇奇怪怪的题,如果是26并不是hel tret而是hel,注意这一点就没什么了

#include<bits/stdc++.h>
using namespace std;
string ge[20] = {"tret","jan", "feb", "mar", "apr", "may", "jun", "jly", "aug", "sep", "oct", "nov", "dec"};
string shi[20] = {"","tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mer", "jou"};

void mars(string s) {//阿拉伯到火星数 
	int n, d1, d2;
	stringstream ss;
	ss << s;
	ss >> n;
	d1 = n % 13, d2 = n / 13;
	if(d2) {
		if(d1)printf("%s %s\n",shi[d2].c_str(), ge[d1].c_str());
		else printf("%s\n",shi[d2].c_str());
	}
	else printf("%s\n",ge[d1].c_str());
}

void earth(string s) {//火星数到阿拉伯数字 
	int p = s.find(" "), l = s.length();
	string d1, d2;
	if(p != string::npos) {
		d1 = s.substr(0, p);
		d2 = s.substr(p+1, l);
	}
	else {
		d1 = "";
		d2 = s;
	}
	int ans = 0;
	if(!d1.empty()) {
		for(int i = 0; i < 13; i++) {
			if(shi[i] == d1) {
				ans += i*13;
				break;
			}
		}
		for(int i = 0; i < 13; i++) {
			if(ge[i] == d2) {
				ans += i;
				break;
			}
		}
		printf("%d\n", ans);	
	} 
	else{
		for(int i = 0; i < 13; i++) {
			if(ge[i] == d2) {
				printf("%d\n",i);
				return;
			}
		}
		for(int i = 1; i < 13; i++) {
			if(shi[i] == d2) {
				printf("%d\n",i*13);
			}
		}
	}
	
}

int main() {
	int n;
	scanf("%d", &n);
	getchar();
	string t;
	for(int i = 0; i < n; i++) {
		getline(cin , t);
		if(isdigit(t[0])){
			mars(t);
		}
		else {
			earth(t);
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值