2017年计蒜客比赛复赛B D两题

来源:互联网 发布:淘宝视频拍摄手机软件 编辑:程序博客网 时间:2024/05/22 08:01

B题目:https://nanti.jisuanke.com/t/15967  

分析:让你判断最后画在该点上的最后的线段标号,采用直线的上点的更新,(斜率存在和斜率不存在)记录每个点的最后的画上去线段的编号

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(1n20000), m(0 \le m \le 20000)m(0m20000),分别表示城市总数和城市群总数。

接下来一共输入 mm 行。

第 ii 行首先输入一个 k_i(1 \le k_i \le n)ki(1kin),表示第 ii个城市群中的城市数为 k_iki。接下来输入 k_iki 个数,表示第 ii 个城市群中每个城市的编号(保证一个城市群内的城市编号不重复且合法,\sum_{i=1}^{m}k_i \le 20000i=1mki20000)。

下一行输入一个整数 m_1(0 \le m_1 \le 20000)m1(0m120000),表示有 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(1ui,vin),ci(1ci106),分别表示快速路连接的两个城市编号和边的距离。

下一行输入一个整数 m_2(0 \le m_2 \le 20000)m2(0m220000),表示有 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(1ai,bim),li(1li106),分别表示快速路连接的两个城市群编号和边的距离。

最后一行输入 s, t(1 \le s, t \le n)s,t(1s,tn),表示起点和终点城市编号。

输出格式

输出一个整数,表示城市 ss 到城市 tt 到最短路。如果不存在路径,则输出-1

样例说明

1 -> 2 - > 5或者1 -> 4 -> 5是最短的路径,总长度为 1212

样例输入

5 42 5 12 2 41 32 3 421 2 91 5 1821 2 61 3 101 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;}




原创粉丝点击