PTA刷题日记14

1131 Subway Map (30 分)

这题强烈建议用链式前向星写,并不用开太大的数组之类的和过多的处理,用edge这个数组记录所在地铁线路即可
就是对每一次读入的起点和终点进行dfs即可

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int head[N], ver[N], nxt[N], edge[N], tot, ans, ma, st, ed;
bool vis[N];
vector<int> path, tmp, line, tline;

void add(int x, int y, int z) {
	ver[++tot] = y, edge[tot] = z;
	nxt[tot] = head[x], head[x] = tot;
}

void dfs(int now, int len, int tra, int d) {
	if(len > ans) return;
	if(now == ed) {
		if(len < ans) {
			ans = len;
			path = tmp;
			ma = tra;
			line = tline;
		}
		else if(tra < ma) {
			path = tmp;
			ma = tra;
			line = tline;
		}
		return;
	}
	int dir = tra;
	for(int i = head[now]; i; i = nxt[i]) {
		int y = ver[i], z = edge[i];
		if(vis[y]) continue;
		vis[y] = 1;
		if(d != z) {
			dir = tra + 1;
			tline.push_back(z);
			tmp.push_back(now);
		}
		dfs(y, len+1, dir, z);
		vis[y] = 0;
		if(d != z) {
			tmp.pop_back();
			tline.pop_back();
		}

	}
}

int main() {
	int n, m, pos, k, a, b;
	scanf("%d",&n);
	for(int i = 1; i <= n; i++) {
		scanf("%d",&m);
		int pre;
		for(int j = 0; j < m; j++) {
			scanf("%d",&pos);
			if(j) add(pre, pos, i), add(pos, pre, i);
			pre = pos;
		}
	}
	scanf("%d",&k);
	while(k--) {
		path.clear(); tmp.clear(); line.clear(); tline.clear();
		ans = 1 << 30, ma = 0;
		memset(vis, 0, sizeof(vis));
		scanf("%d %d",&st, &ed);
		vis[st] = 1;
		dfs(st, 0, 0, -1);
		path.push_back(ed);
		printf("%d\n",ans);
		for(int i = 0; i < line.size(); i++) {
			printf("Take Line#%d from %04d to %04d.\n",line[i], path[i], path[i+1]);
		}
	}
	return 0;
}

1132 Cut Integer (20 分)

不知道会不会有前置0的问题,我大概算了一下应该是不会溢出的,可是为了避免无谓的错误我都考虑了
还有PTA里读入long long一定要用%lld,编译器不同,可能自己电脑编译是没问题的

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

string i2s(int n) {
	stringstream ss;
	string s;
	ss << n;
	ss >> s;
	return s;
}

int main() {
	ll z, n;
	scanf("%d", &z);
	while(z--) {
		scanf("%d",&n);
		string s = i2s(n);
		ll k = s.length() / 2;
		k = pow(10, k);
		ll n1 = n / k, n2 = n % k;
		if(!n1 || !n2) printf("No\n");
		else {
			if(n % (n1 * n2)) printf("No\n");
			else printf("Yes\n");
		}
	}
	
	
	return 0;
}

1133 Splitting A Linked List (25 分)

我把链表在从头至尾遍历的过程中切分成三块,分别是负数一块,【0,k】,大于k,这样输出的时候要注意一下前面两个链表是不是为空,空链表处理起来会有所不同

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int l1[N], l2[N], l3[N], nxt[N], val[N];

int main() {
	int n, k, head, th, tn, t;
	scanf("%d %d %d",&head, &n, &k);
	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, s = 0;
	for(int i = 0; i < n; i++) {
		if(now == -1) break;
		if(val[now] < 0) l1[p++] = now;
		else if(val[now] <= k) l2[q++] = now;
		else l3[s++] = now;
		now = nxt[now];
	}
	for(int i = 0; i < p; i++) {
		if(i) printf("%05d\n", l1[i]);
		printf("%05d %d ", l1[i], val[l1[i]]);
	}
	for(int i = 0; i < q; i++) {
		if(p || i) printf("%05d\n", l2[i]);
		printf("%05d %d ", l2[i], val[l2[i]]);
	}
	for(int i = 0; i < s; i++) {
		if(p || q || i) printf("%05d\n", l3[i]);
		printf("%05d %d ", l3[i], val[l3[i]]);
	}
	printf("-1");
	return 0;
}

1134 Vertex Cover (25 分)

不要数点,数边,记录每个点连接的边,每次查询一个点先加上它连接的边数,再减去这些边中已经被访问过的,并且标记与它相连的边已经被标记过一遍了

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
int f[N];
vector<int> v[N];
unordered_map<int, int> mp;

int main() {
	int n, m, a, b, k, num, t;
	scanf("%d %d", &n, &m);
	for(int i = 0; i < m; i++) {
		scanf("%d %d", &a, &b);
		v[a].push_back(b);
		v[b].push_back(a);
		mp[a]++;
		mp[b]++;
	}
	scanf("%d",&k);
	while(k--) {
		num = 0;
		memset(f, 0, sizeof(f));
		scanf("%d",&t);
		while(t--) {
			scanf("%d",&a);
			if(mp.count(a)) {
				num += mp[a];
				if(!f[a]) f[a] = 1;
				else {
					num -= f[a];
				}
				for(int i = 0; i < v[a].size(); i++) {
					int y = v[a][i];
					f[y]++;
				}	
			}
		}
		if(num == m) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

1135 Is It A Red-Black Tree (30 分)

大无语,一顿操作段错误
如果有重复元素用前中序重构树肯定是有问题的,但是我想他都没给BST怎么定义应该不会卡这个吧,结果还是我太天真了。。。
必须用给定的顺序(也就是前序遍历)逐一插入元素建树,所以前序遍历和数据的插入顺序一致(学会新知识),再dfs一遍就ac了

#include<bits/stdc++.h>
using namespace std;
bool f = 0;
struct node{
	int val, color;
	node *l, *r;
}; 

node* New(int x) {
	node* t = new node;
	if(x < 0) t->color = -1;
	else t->color = 1;
	t->val = t->color * x;
	t->l = t->r = NULL;
	return t;
}

void insert(node* &root, int x) {
	if(root == NULL) {
		root = New(x);
	}
	else {
		if(root->val > abs(x)) insert(root->l, x);
		else insert(root->r, x);
	}
} 

int dfs(node* root, int c) {
	if(root == NULL) return 1; 
	if(c == -1 && root->color != 1) f = 1;
	int lnum = dfs(root->l, root->color);
	int rnum = dfs(root->r, root->color);
	if(lnum != rnum) f = 1;
	if(root->color == 1) return lnum+1;
	else return lnum;
}

int main() {
	int n, k, a;
	scanf("%d",&k);
	while(k--) {
		f = 0;
		scanf("%d",&n);
		node* root = NULL;
		if(n) {
			for(int i = 0; i < n; i++) {
				scanf("%d",&a);
				insert(root, a);
			}
			dfs(root, 1);
			if(f || root->color != 1) printf("No\n");
			else printf("Yes\n");	
		}
		else printf("Yes\n");
	}
	return 0;
}

1136 A Delayed Palindrome (20 分)

就是一个大数的处理,估计给的数位数没有特别大,算起来还是很快的,相加然后判断回文,低位存低位,高位存高位,搞清楚这个就行,或者反过来的话自己脑子清醒就行

#include<bits/stdc++.h> 
using namespace std;
const int N = 1e5 + 5;
struct bign{
	int d[N];
	int l;
}a, b;

bign add(bign a) {
	int s, p = 0;
	bign c; c.l = 0;
	for(int i = 0; i < a.l; i++) {
		s = a.d[i] + a.d[a.l - i - 1] + p;
		p = s / 10;
		c.d[c.l++] = s % 10;
	}
	if(p) c.d[c.l++] = p;
	return c;
}

bool isp(bign a) {
	for(int i = 0; i < a.l; i++) {
		if(a.d[i] != a.d[a.l - i - 1]) return false;
	}
	return true;
}

void output1(bign a) {
	for(int i = a.l - 1; i >= 0; i--) printf("%d",a.d[i]);
}

void output2(bign a) {
	for(int i = 0; i < a.l; i++) printf("%d",a.d[i]);
}

int main() {
	string s;
	cin >> s;
	for(int i = s.length()-1; i >= 0; i--) {
		a.d[a.l++] = s[i] - '0';
	}
	for(int i = 0; i < 10; i++) {
		if(isp(a)) {
			output1(a);
			printf(" is a palindromic number.\n");
			return 0;
		}
		b = add(a);
		output1(a);
		printf(" + ");
		output2(a);
		printf(" = ");
		output1(b);
		printf("\n");
		a = b;
	}
	printf("Not found in 10 iterations.\n");
	return 0;
} 

1140 Look-and-say Sequence (20 分)

说实话,我觉得这个题目解释着实说的不清不楚(我觉得很多题都说的不清不楚,这个特别)
就是下一个序列是对前一个序列中每一个连续的数字a连续了b次就写作ab,1次也算,字符串处理题
搞清楚题意以后可以看到n很小,所以直接暴力即可

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

int main() {
	int n;
	string a, b;
	cin >> a >> n;
	for(int i = 1; i < n; i++) {
		int l = a.length();
		int num = 0;
		char ch = ',';
		b = "";
		for(int j = 0; j < l; j++) {
			if(ch == a[j]) num++;
			else {
				if(num) b += ch, b += '0'+num;
				num = 1;	
			}
			ch = a[j];
		}
		if(num) b += ch, b += '0'+num;
		a = b;
	} 
	cout<<a<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值