2017年计蒜客比赛复赛B D两题
2017-06-11 13:37
351 查看
B题目:https://nanti.jisuanke.com/t/15967
分析:让你判断最后画在该点上的最后的线段标号,采用直线的上点的更新,(斜率存在和斜率不存在)记录每个点的最后的画上去线段的编号
AC代码:
注意:此题会卡精度啊,必须加上0.5进行四舍五入啊,gg!
D题目:https://nanti.jisuanke.com/t/15969
百度地图上有 nn 个城市,城市编号依次为 11 到 nn。地图中有若干个城市群,编号依次为 11 到 mm。每个城市群包含一个或多个城市;每个城市可能属于多个城市群,也可能不属于任何城市群。
地图中有两类道路。第一类道路是 城市之间的快速路,两个城市 u,vu,v 之间增加一条距离为 cc 的边;第二类道路是 城市群之间的高速路,连接两个城市群 a,ba,b,通过这条高速路,城市群 aa 里的每个城市与城市群 bb 里的每个城市之间两两增加一条距离为 cc 的边。图中所有边均为无向边。
你需要计算从城市 ss 到城市 tt 的最短路。
\le n \le 20000),n(1≤n≤20000), m(0
\le m \le 20000)m(0≤m≤20000),分别表示城市总数和城市群总数。
接下来一共输入 mm 行。
第 ii 行首先输入一个 k_i(1
\le k_i \le n)ki(1≤ki≤n),表示第 ii个城市群中的城市数为 k_iki。接下来输入 k_iki 个数,表示第 ii 个城市群中每个城市的编号(保证一个城市群内的城市编号不重复且合法,\sum_{i=1}^{m}k_i
\le 20000∑i=1mki≤20000)。
下一行输入一个整数 m_1(0
\le m_1 \le 20000)m1(0≤m1≤20000),表示有 m_1m1 条第一类道路,即 城市之间的快速路。
接下来 m_1m1 行,每行输入三个整数 u_i,v_i(1
\le u_i, v_i \le n),c_i(1 \le c_i \le 10^6)ui,vi(1≤ui,vi≤n),ci(1≤ci≤106),分别表示快速路连接的两个城市编号和边的距离。
下一行输入一个整数 m_2(0
\le m_2 \le 20000)m2(0≤m2≤20000),表示有 m_2m2 条第二类道路,即 城市群之间的高速路。
接下来 m_2m2 行,每行输入三个整数 a_i,b_i(1
\le a_i, b_i \le m),l_i(1 \le l_i \le 10^6)ai,bi(1≤ai,bi≤m),li(1≤li≤106),分别表示快速路连接的两个城市群编号和边的距离。
最后一行输入 s,
t(1 \le s, t \le n)s,t(1≤s,t≤n),表示起点和终点城市编号。
分析:基本思路:用优先队列优化一下的Dijkstra()算法,问题在于,我们如何见图,城市之间的图容易见,主要是群之间如何建立图,城市和群之间建图,首先我们将群号分成两部分n+1~n+m表示第一批的序号,n+m+1~n+m+m表示第二批的序号,那么建图就可以转成,城市到第一批的建立,第一批到第二批群之间的建立,其实说白了就是转折:城市-群-城市,这样解决了题目中每个群之间所有的所有城市建录得问题
AC 代码:
当然,优先队列用pair可能不好理解,那么我们可以使用,自定义结构体:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
const int max_m = 20010;
const LL INF = 0x3f3f3f3f3f3f3f3f;
int n,m;
int a,b,m1,m2;
LL c;
vector<pair<int,LL> >gra[3*max_m];
LL d[3*max_m];
struct HeapNode {
int d,u;
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
} p,pp;
void dijkstra(int s) {
priority_queue<HeapNode>Q;
for(int i = 1; i <= n+2*m; i++) d[i] = INF;
d[s] = 0;
p.u = s;
p.d = 0;
Q.push(p);
while(!Q.empty()) {
p = Q.top();
Q.pop();
int u = p.u;
for(int i = 0; i < gra[u].size(); i++) {
int to = (gra[u][i].first);
int dist = gra[u][i].second;
if(d[to] > d[u] + dist) {
d[to] = d[u] + dist;
pp.u = to;
pp.d = d[to];
Q.push(pp);
}
}
}
}
int main() {
scanf("%d%d",&n,&m);
int k;
for(int i = 1; i <= m; i++) {
scanf("%d",&k);
for(int j = 0; j < k; j++) {
scanf("%d",&a);
gra[a].push_back(pair<int,int>(n+i,0));//建立城市到群号之间的距离为0
gra[n+m+i].push_back(pair<int,int>(a,0));//建立群号到城市之间的图
}
}
scanf("%d",&m1);
while(m1--) {
scanf("%d%d%lld",&a,&b,&c);
gra[a].push_back(pair<int,int>(b,c));//建立城市之间的图
gra[b].push_back(pair<int,int>(a,c));
}
scanf("%d",&m2);
for(int i = 0; i < m2; ++i) {
scanf("%d%d%lld",&a,&b,&c);
gra[a+n].push_back(pair<int,int>(b+m+n,c));//建立群与群之间的图
gra[b+n].push_back(pair<int,int>(a+m+n,c));
}
scanf("%d%d",&a,&b);
if(a == b) {
printf("0\n");
return 0;
}
dijkstra(a);
if(d[b] == INF) {
printf("-1\n");
} else {
printf("%lld\n",d[b]);
}
return 0;
}
分析:让你判断最后画在该点上的最后的线段标号,采用直线的上点的更新,(斜率存在和斜率不存在)记录每个点的最后的画上去线段的编号
AC代码:
#include <iostream> #include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> #include <set> using namespace std; const int max_n = 255; int n,m,q; int gra[max_n][max_n]; int a,b,c,d; int main() { scanf("%d%d",&n,&m); memset(gra,0,sizeof(gra)); for(int i = 1; i <= n; i++) { scanf("%d%d%d%d",&a,&b,&c,&d); if(a == c) { int y = b,my=d; if(b > d) { y = d; my = b; } for(; y <= my; ++y) { gra[a][y] = i; } } else { double k = ((b-d)*1.0)/(a-c); int x = a,mx = c; if(a > c) { x = c; mx = a; } for(; x <= mx; x++) { int y = (k*(x-a)+b)*1.0+0.5; if((b-y)*(c-x) == (d-y)*(a-x)) { gra[x][y] = i; } } } } scanf("%d",&q); while(q--) { scanf("%d%d",&a,&b); printf("%d\n",gra[a][b]); } return 0; }
注意:此题会卡精度啊,必须加上0.5进行四舍五入啊,gg!
D题目:https://nanti.jisuanke.com/t/15969
百度地图上有 nn 个城市,城市编号依次为 11 到 nn。地图中有若干个城市群,编号依次为 11 到 mm。每个城市群包含一个或多个城市;每个城市可能属于多个城市群,也可能不属于任何城市群。
地图中有两类道路。第一类道路是 城市之间的快速路,两个城市 u,vu,v 之间增加一条距离为 cc 的边;第二类道路是 城市群之间的高速路,连接两个城市群 a,ba,b,通过这条高速路,城市群 aa 里的每个城市与城市群 bb 里的每个城市之间两两增加一条距离为 cc 的边。图中所有边均为无向边。
你需要计算从城市 ss 到城市 tt 的最短路。
输入格式
第一行输入 n(1\le n \le 20000),n(1≤n≤20000), m(0
\le m \le 20000)m(0≤m≤20000),分别表示城市总数和城市群总数。
接下来一共输入 mm 行。
第 ii 行首先输入一个 k_i(1
\le k_i \le n)ki(1≤ki≤n),表示第 ii个城市群中的城市数为 k_iki。接下来输入 k_iki 个数,表示第 ii 个城市群中每个城市的编号(保证一个城市群内的城市编号不重复且合法,\sum_{i=1}^{m}k_i
\le 20000∑i=1mki≤20000)。
下一行输入一个整数 m_1(0
\le m_1 \le 20000)m1(0≤m1≤20000),表示有 m_1m1 条第一类道路,即 城市之间的快速路。
接下来 m_1m1 行,每行输入三个整数 u_i,v_i(1
\le u_i, v_i \le n),c_i(1 \le c_i \le 10^6)ui,vi(1≤ui,vi≤n),ci(1≤ci≤106),分别表示快速路连接的两个城市编号和边的距离。
下一行输入一个整数 m_2(0
\le m_2 \le 20000)m2(0≤m2≤20000),表示有 m_2m2 条第二类道路,即 城市群之间的高速路。
接下来 m_2m2 行,每行输入三个整数 a_i,b_i(1
\le a_i, b_i \le m),l_i(1 \le l_i \le 10^6)ai,bi(1≤ai,bi≤m),li(1≤li≤106),分别表示快速路连接的两个城市群编号和边的距离。
最后一行输入 s,
t(1 \le s, t \le n)s,t(1≤s,t≤n),表示起点和终点城市编号。
输出格式
输出一个整数,表示城市 ss 到城市 tt 到最短路。如果不存在路径,则输出-1。
样例说明
1 -> 2 - > 5或者
1 -> 4 -> 5是最短的路径,总长度为 1212。
样例输入
5 4 2 5 1 2 2 4 1 3 2 3 4 2 1 2 9 1 5 18 2 1 2 6 1 3 10 1 5
样例输出
12
分析:基本思路:用优先队列优化一下的Dijkstra()算法,问题在于,我们如何见图,城市之间的图容易见,主要是群之间如何建立图,城市和群之间建图,首先我们将群号分成两部分n+1~n+m表示第一批的序号,n+m+1~n+m+m表示第二批的序号,那么建图就可以转成,城市到第一批的建立,第一批到第二批群之间的建立,其实说白了就是转折:城市-群-城市,这样解决了题目中每个群之间所有的所有城市建录得问题
AC 代码:
#include <iostream> #include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> #include <set> using namespace std; typedef long long LL; const int max_m = 20010; const LL INF = 0x3f3f3f3f3f3f3f3f; int n,m; int a,b,m1,m2; LL c; vector<pair<int,LL> >gra[3*max_m]; LL d[3*max_m]; void dijkstra(int s) { priority_queue<pair<LL,int> >Q;//这样定义主要是为了以pair的第一个元素排序 for(int i = 1; i <= n+2*m; i++) d[i] = INF; d[s] = 0; Q.push(pair<int,LL>(0,s)); while(!Q.empty()) { int u = Q.top().second; Q.pop(); for(int i = 0; i < gra[u].size(); i++) { int to = (gra[u][i].first); int dist = gra[u][i].second; if(d[to] > d[u] + dist) { d[to] = d[u] + dist; Q.push(pair<int,int>(-d[to],to));//为什么这里我们要-d[to]呢?原因在于优先队列默认从大到小排序,那么-d[to]就得出最小的一定在优先队列的首位 } } } } /** 定义:1~n表示城市编号,n+1~n+m表示群的编号,n+m+1 ~ n+2*m表示群的编号 即有n+i对应的群编号 = n+m+i对应的群编号; */ int main() { scanf("%d%d",&n,&m); int k; for(int i = 1; i <= m; i++) { scanf("%d",&k); for(int j = 0; j < k; j++) { scanf("%d",&a); gra[a].push_back(pair<int,int>(n+i,0));//建立城市到群号之间的距离为0 gra[n+m+i].push_back(pair<int,int>(a,0));//建立群号到城市之间的图 } } scanf("%d",&m1); while(m1--) { scanf("%d%d%lld",&a,&b,&c); gra[a].push_back(pair<int,int>(b,c));//建立城市之间的图 gra[b].push_back(pair<int,int>(a,c)); } scanf("%d",&m2); for(int i = 0; i < m2; ++i) { scanf("%d%d%lld",&a,&b,&c); gra[a+n].push_back(pair<int,int>(b+m+n,c));//建立群与群之间的图 gra[b+n].push_back(pair<int,int>(a+m+n,c)); } scanf("%d%d",&a,&b); if(a == b) { printf("0\n"); return 0; } dijkstra(a); if(d[b] == INF) { printf("-1\n"); } else { printf("%lld\n",d[b]); } return 0; }
当然,优先队列用pair可能不好理解,那么我们可以使用,自定义结构体:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
const int max_m = 20010;
const LL INF = 0x3f3f3f3f3f3f3f3f;
int n,m;
int a,b,m1,m2;
LL c;
vector<pair<int,LL> >gra[3*max_m];
LL d[3*max_m];
struct HeapNode {
int d,u;
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
} p,pp;
void dijkstra(int s) {
priority_queue<HeapNode>Q;
for(int i = 1; i <= n+2*m; i++) d[i] = INF;
d[s] = 0;
p.u = s;
p.d = 0;
Q.push(p);
while(!Q.empty()) {
p = Q.top();
Q.pop();
int u = p.u;
for(int i = 0; i < gra[u].size(); i++) {
int to = (gra[u][i].first);
int dist = gra[u][i].second;
if(d[to] > d[u] + dist) {
d[to] = d[u] + dist;
pp.u = to;
pp.d = d[to];
Q.push(pp);
}
}
}
}
int main() {
scanf("%d%d",&n,&m);
int k;
for(int i = 1; i <= m; i++) {
scanf("%d",&k);
for(int j = 0; j < k; j++) {
scanf("%d",&a);
gra[a].push_back(pair<int,int>(n+i,0));//建立城市到群号之间的距离为0
gra[n+m+i].push_back(pair<int,int>(a,0));//建立群号到城市之间的图
}
}
scanf("%d",&m1);
while(m1--) {
scanf("%d%d%lld",&a,&b,&c);
gra[a].push_back(pair<int,int>(b,c));//建立城市之间的图
gra[b].push_back(pair<int,int>(a,c));
}
scanf("%d",&m2);
for(int i = 0; i < m2; ++i) {
scanf("%d%d%lld",&a,&b,&c);
gra[a+n].push_back(pair<int,int>(b+m+n,c));//建立群与群之间的图
gra[b+n].push_back(pair<int,int>(a+m+n,c));
}
scanf("%d%d",&a,&b);
if(a == b) {
printf("0\n");
return 0;
}
dijkstra(a);
if(d[b] == INF) {
printf("-1\n");
} else {
printf("%lld\n",d[b]);
}
return 0;
}
相关文章推荐
- 完美未来之星编程比赛 复赛第一场 图像融合
- 美团点评2017年CodeM大赛-复赛 A 城市网络(倍增)
- 关于2017年无人驾驶智能车辆比赛,参赛报名日期调整的通知
- 完美未来之星编程比赛 复赛第一场 时间计算
- 2017年的数学建模比赛已经结束了
- 2017年山东省机器人比赛 双足竟步 arduino源代码(删去了关键步态程序 gongneng1 和 gongneng2)
- NOIP2013,复赛及同步赛,报名及比赛,专题页面
- [置顶] 2017年全国数学建模比赛赛后感想
- 2017年第六届数学中国数学建模国际赛(小美赛)比赛心得
- 2017年山东省双足机器人一等奖(四自由度)arduino源程序+比赛心得
- 完美未来之星编程比赛 复赛第二场 发放激活码
- 【比赛】百度之星2017 复赛
- 天池工业AI大赛-智能制造质量预测 比赛历程和技术方案总结复赛48名
- 完美未来之星编程比赛 复赛第一场 文字处理屏蔽字库
- 2017年个人计划
- 2018年全国多校算法寒假训练营练习比赛(第五场)
- flashclash比赛RIA获奖作品
- 2017年直播类APP开发市场新定位
- 【每日安全资讯】卡巴斯基实验室指网络犯罪分子通过恶意挖矿软件在2017年获利数百万美元
- Mekka ’97 4K Intro比赛的一等奖作品