思路:本题的区间已经按照开始时间排序过,因此我们只需要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
*/