杭州达西信息技术有限公司笔试

思路:本题的区间已经按照开始时间排序过,因此我们只需要O(n)扫描一遍,进行区间合并即可。

上图的两个区间,代表的含义是左区间的右端点小于右区间的左端点,是不存在重叠的情况的。

上图的两个区间,代表的含义是左区间的右端点大于等于右区间的左端点,存在重叠可以合并。

讨论合并区间后的区间右端点:

上图的区间合并后,右端点是右区间的右端点。

上图的区间合并后,右端点是左区间的右端点。

因此我们应该取两个存在重叠区间的两个右端点的最大值。

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

vector<vector<int>> merge(vector<vector<int>> intervals){
	int n = intervals.size(), i, IntervalL, IntervalR;
	vector<vector<int>> ans;
	IntervalL = intervals[0][0];
	IntervalR = intervals[0][1];
	for(i = 1; i < n; ++ i){
		if(intervals[i][0] <= IntervalR){
			IntervalR = max(IntervalR, intervals[i][1]);
		}else{
			vector<int> interval;
			interval.push_back(IntervalL);
			interval.push_back(IntervalR);
			ans.push_back(interval);
			IntervalL = intervals[i][0];
			IntervalR = intervals[i][1];
		}
	}
	vector<int> interval;
	interval.push_back(IntervalL);
	interval.push_back(IntervalR);
	ans.push_back(interval);
	return ans;
}

int main(){
	vector<vector<int>> Intervals;
	int n, L, R, i;
	cin >> n;
	for(i = 0; i < n; ++ i){
		cin >> L >> R;
		vector<int> interval;
		interval.push_back(L);
		interval.push_back(R);
		Intervals.push_back(interval);
	}
	Intervals = merge(Intervals);
	for(i = 0; i < Intervals.size(); ++ i){
		cout << Intervals[i][0] << " " << Intervals[i][1] << endl;
	}
	return 0;	
}

思路:我们只需要设置两个单独的索引指针,遍历模式串abbr,如果指向的是字母,就直接判断是否匹配;如果指向的是数字,那么需要先解析出数字,让后将串s的索引指针直接后移。如果最终匹配的话,那么两个指针一定都停留在串尾。

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

bool valid(string word, string abbr){
	int index1 = 0, index2 = 0, n1 = word.size(), n2 = abbr.size(), num;
	while( index1 < n1 && index2 < n2 ){
		if( abbr[index2] >= 'a' && abbr[index2] <= 'z' ){ // 如果是字母 
			if( word[index1] != abbr[index2] ) return false;
			++ index1;
			++ index2;
		}else{ // 如果是数字 
			num = 0;
			while( abbr[index2] >= '0' && abbr[index2] <= '9' && index2 < n2 ){
				num = num * 10 + abbr[index2] - '0';
				++ index2;
			}
			index1 += num;
		}
	}
	return index1 == n1 && index2 == n2;
}

int main(){
	string s, abbr;
	cin >> s >> abbr;
	cout << ( valid(s,abbr) ? "true" : "false" );
	return 0;
}

思路:直接搜索start-end的所有路径得到结果。答案路径一定不会经过一条边多次,亦不会在环路上跑,因为按位或操作具有两种性值:1. 在都是正整数的情况下,按位或的结果不可能变小  2. 多次与同一个值进行按位或的结果与一次的结果相同。

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

const int MaxN = 10010;
int cnt, Head[MaxN], To[MaxN], Weight[MaxN], Next[MaxN], Ans; 
bool visited[MaxN];

void add(int from, int to, int value){
	Next[++ cnt] = Head[from];
	Head[from] = cnt;
	To[cnt] = to;
	Weight[cnt] = value;
}

void DFS(int S, int O, int OrResult){
	if(S == O){
		Ans = min(Ans, OrResult);
		return;
	}
	int to;
	for(int E = Head[S]; E != 0; E = Next[E]){
		to = To[E];
		if(!visited[to]){
			visited[to] = true;
			DFS(to, O, OrResult | Weight[E]);
			visited[to] = false;
		}
	}
}

int minPath(int n, vector<vector<int>> edges, int start, int end){
	int m = edges.size(), i, j;
	for(i = 0; i < m; ++ i){
		add(edges[i][0], edges[i][1], edges[i][2]);
	}
	Ans = 0x3f3f3f3f;
	visited[start] = true;
	DFS(start, end, 0);
	return Ans;
}

int main(){
	int n, i, u, v, w, start, end;
	cin >> n;
	vector<vector<int>> edges;
	for(i = 0; i < n; ++ i){
		vector<int> edge;
		cin >> u >> v >> w;
		edge.push_back(u);
		edge.push_back(v);
		edge.push_back(w);
		edges.push_back(edge);
	}
	cin >> n >> start >> end;
	cout << minPath(n, edges, start, end);
	return 0;
} 
//测试数据
/*
3
1 2 1
2 3 3
1 3 100
3 1 3
*/

猜你喜欢

转载自blog.csdn.net/qq_39304630/article/details/112723839