2016年天梯赛 L3 题解

L1 - L2题解链接:https://blog.csdn.net/mldl_/article/details/114991298

7-13 是否完全二叉搜索树 (30分)

思路
二叉树常规操作,根据要求构造二叉树,BFS判断是否为满二叉树即可。

ACcode

#include <bits/stdc++.h>

using namespace std;

const int maxn = 2e6 + 5;
int t[maxn], a[maxn];
vector<int> res;
queue<int> qu;

int main(){
	
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i];

	memset(t, -1, sizeof(t));	
	for(int i = 1; i <= n; i++){
		int pos = 1;
		while(1){
			if(t[pos] == -1){
				t[pos] = a[i];
				break;
			}
			else if(a[i] > t[pos]) pos = pos * 2;
			else pos = pos * 2 + 1;
		}
		
	}
	
	int flag = 1;
	for(int i = 1; i <= n; i++) if(t[i] == -1) flag = 0;
	qu.push(1);
	while(!qu.empty()){
		int now = qu.front(); qu.pop();
		res.push_back(t[now]);
		if(t[now*2] != -1) qu.push(now*2);
		if(t[now*2+1] != -1) qu.push(now*2+1);
	}
	
	if(flag) cout << "YES" << endl;
	else cout << "NO" << endl;
	for(int i = 0; i < n; i++) cout << (i == 0 ? "" : " ") << res[i];
			
	return 0;
}

7-14 直捣黄龙 (30分)

思路
dijkstra 跑最短路(堆优化,写结构体自定义排序维护题目信息),定义 pre 数组记录前导点回归路径和计数数组统计路径数即可。

ACcode

#include <bits/stdc++.h>
#define PI acos(-1)
#define ld long double
#define IOS     cin.tie(0), ios::sync_with_stdio(false)
#define ll long long
#define endl "\n"
const double eps = 1e-8;
const ll INF = 0x3f3f3f3f;
const ll mod = 998244353;
const int maxn = 1e6 + 5;
using namespace std;

typedef struct Node{
	ll id;
	ll dis, cnt, w;
} node;

bool operator < (node A, node B){
	if(A.dis == B.dis){
		if(A.cnt == B.cnt) return A.w < B.w;
		return A.cnt < B.cnt;
	}
	return A.dis > B.dis;
}

map<string, int> id;
map<int, string> name;
vector<pair<ll, ll> > ma[300];
ll w[300], pre[300];
ll dis[300], cnt[300], val[300], sum[300];
priority_queue<node> qu;

void path(int x){
	if(pre[x] == -1){
		cout << name[x];
		return;
	}
	path(pre[x]);
	cout << "->" << name[x];
}

int main(){
	
	IOS;
	int n, m; string a, b;
	cin >> n >> m >> a >> b;
	id[a] = 1; name[1] = a;
	string s; int x;
	for(int i = 2; i <= n; i++){
		cin >> s >> x;
		id[s] = i; name[i] = s;
		w[i] = x;
	}
	int S = id[a], E = id[b];
	for(int i = 1; i <= m; i++){
		cin >> a >> b >> x;
		int u = id[a], v = id[b];
		ma[u].push_back({v, x});
		ma[v].push_back({u, x});
	}
	
	for(int i = 1; i <= n; i++) dis[i] = 1e18, cnt[i] = val[i] = -1e18, sum[i] = 0;
	pre[S] = -1; dis[S] = cnt[S] = val[S] = 0; sum[S] = 1;
	qu.push({S, 0, 0, 0});
	node now, next;
	while(!qu.empty()){
		now = qu.top(); qu.pop();
		for(auto u : ma[now.id]){
			next.id = u.first;
			next.dis = now.dis + u.second;
			next.cnt = now.cnt + 1;
			next.w = now.w + w[next.id];
			if(next.dis < dis[next.id]){
				dis[next.id] = next.dis;
				cnt[next.id] = next.cnt;
				val[next.id] = next.w;
				sum[next.id] = sum[now.id];
				pre[next.id] = now.id;
				qu.push(next);
			} 
			else if(next.dis == dis[next.id]){
				sum[next.id] += sum[now.id];
				if(next.cnt > cnt[next.id]){
					cnt[next.id] = next.cnt;
					val[next.id] = next.w;
					pre[next.id] = now.id;
					qu.push(next);
				}
				else if(next.cnt == cnt[next.id]){
					if(next.w > val[next.id]){
						val[next.id] = next.w;
						pre[next.id] = now.id;
						qu.push(next);
					}
				}
			}
		}
		ma[now.id].clear();
	}
	
	path(E); cout << endl;
	cout << sum[E] << " " << dis[E] << " " << val[E] << endl;
	
	return 0;
}

7-15 水果忍者 (30分)

思路
思维题。
题目保证有解,一定存在一条直线通过两条线段端点(一个上端点一个下端点), O ( n 2 ) O(n^2) O(n2) 判断即可。

Accode

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

typedef struct Node{
	int x;
	int y1, y2;
} node;

node a[1005];

int main(){
	
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i].x >> a[i].y1 >> a[i].y2;
	
	
	for(int i = 1; i <= n; i++){
		pair<ll, ll> k1 = {3e6, 1}, k2 = {-3e6, 1}; int res = -1;
		for(int j = 1; j <= n; j++){
			if(i == j) continue;
			ll y = a[j].y1 - a[i].y2; // 上 
			ll x = a[j].x - a[i].x; if(x < 0) x *= -1, y *= -1;
			if(y * k1.second < k1.first * x) k1 = {y, x}, res = j;
			y = a[j].y2 - a[i].y2; // 下 
			x = a[j].x - a[i].x; if(x < 0) x *= -1, y *= -1;
			if(y * k2.second > k2.first * x) k2 = {y, x};
		}
		if(k1.first * k2.second >= k2.first * k1.second){
			cout << a[i].x << " " << a[i].y2 << " " << a[res].x << " " << a[res].y1;
			break;
		}
		k1 = {3e6, 1}, k2 = {-3e6, 1}; res = -1;
		for(int j = 1; j <= n; j++){
			if(i == j) continue;
			ll y = a[j].y1 - a[i].y1; // 上 
			ll x = a[j].x - a[i].x; if(x < 0) x *= -1, y *= -1;
			if(y * k1.second < k1.first * x) k1 = {y, x}, res = j;
			y = a[j].y2 - a[i].y1; // 下 
			x = a[j].x - a[i].x; if(x < 0) x *= -1, y *= -1;
			if(y * k2.second > k2.first * x) k2 = {y, x};
		}
		if(k1.first * k2.second >= k2.first * k1.second){
			cout << a[i].x << " " << a[i].y1 << " " << a[res].x << " " << a[res].y1;
			break;
		}
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值