• L2-4 网红点打卡攻略 2020年团体程序设计天梯赛-总决赛


    题目:
    一个旅游景点,如果被带火了的话,就被称为“网红点”。大家来网红点游玩,俗称“打卡”。在各个网红点打卡的快(省)乐(钱)方法称为“攻略”。你的任务就是从一大堆攻略中,找出那个能在每个网红点打卡仅一次、并且路上花费最少的攻略。

    输入格式:
    首先第一行给出两个正整数:网红点的个数 N(1<N≤200)和网红点之间通路的条数 M。随后 M 行,每行给出有通路的两个网红点、以及这条路上的旅行花费(为正整数),格式为“网红点1 网红点2 费用”,其中网红点从 1 到 N 编号;同时也给出你家到某些网红点的花费,格式相同,其中你家的编号固定为 0。
    再下一行给出一个正整数 K,是待检验的攻略的数量。随后 K 行,每行给出一条待检攻略,格式为:n V​1​​ V​2​​ ⋯ V​n
    其中 n(≤200) 是攻略中的网红点数,Vi是路径上的网红点编号。这里假设你从家里出发,从V1开始打卡,最后从 Vn回家。

    输出格式:

    在第一行输出满足要求的攻略的个数。
    在第二行中,首先输出那个能在每个网红点打卡仅一次、并且路上花费最少的攻略的序号(从 1 开始),然后输出这个攻略的总路费,其间以一个空格分隔。如果这样的攻略不唯一,则输出序号最小的那个。
    题目保证至少存在一个有效攻略,并且总路费不超过 1e9.

    输入样例:

    6 13
    0 5 2
    6 2 2
    6 0 1
    3 4 2
    1 5 2
    2 5 1
    3 1 1
    4 1 2
    1 6 1
    6 3 2
    1 2 1
    4 5 3
    2 0 2
    7
    6 5 1 4 3 6 2
    6 5 2 1 6 3 4
    8 6 2 1 6 3 4 5 2
    3 2 1 5
    6 6 1 3 4 5 2
    7 6 2 1 3 4 5 2
    6 5 2 1 4 3 6

    输出样例:

    3
    5 11

    样例说明:
    第 2、3、4、6 条都不满足攻略的基本要求,即不能做到从家里出发,在每个网红点打卡仅一次,且能回到家里。所以满足条件的攻略有 3 条。
    第 1 条攻略的总路费是:(0->5) 2 + (5->1) 2 + (1->4) 2 + (4->3) 2 + (3->6) 2 + (6->2) 2 + (2->0) 2 = 14;
    第 5 条攻略的总路费同理可算得:1 + 1 + 1 + 2 + 3 + 1 + 2 = 11,是一条更省钱的攻略;
    第 7 条攻略的总路费同理可算得:2 + 1 + 1 + 2 + 2 + 2 + 1 = 11,与第 5 条花费相同,但序号较大,所以不输出。

    打比赛的时候,疑惑为什么样例说明第3条不满足。卡在了阅读理解上了。

    题解:给你k个攻略,每个攻略要求你检查可行性。如果可行(题目保证一定有可行的),再求攻略的最少花费,如果有相同的最少花费攻略,优先输出序号最小的。第一行输出可行的攻略数量,第二行输出最少花费的最小ID和最少花费。
    建议用邻接矩阵建图。


    可行性:
    1、n个点都要访问且只访问一次(用一个vis数组记录一下输入的攻略路线:vis[v[i]]++,检查一下vis[1~n],要求都是1)。2、要求从0出发经过攻略路线再到0要有边连接(在检查的过程中计算花费)。
    最少花费ID和最少花费:在可行性的基础上选择一下就好。

    补题代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int N = 200+5;
    #define inf 0x3f3f3f3f
    #define mod 998244353
    #define pre(a,b,c) for(int a=b;a<c;a++)
    #define pres(a,b,c) for(int a=b;a<=c;a++)
    int G[N][N];
    int a[N],sum,q,vis[N],n,m;
    bool BFS(int s) {
        for(int j = 1;j <= n;j++) {
            if(vis[j]!=1) {
                return false;
            }
        }
        sum = 0;
        for(int i = 0;i < q;i++) {
            if(G[s][a[i]]==inf) {
                return false;
            }
            sum += G[s][a[i]];
            s = a[i];
        }
        if(G[s][0]==inf) {
            return false;
        }
        sum += G[s][0];
        return true;
    }
    int main() {
        cin>>n>>m;
        memset(G,inf,sizeof G);
        for(int i = 0,u,v,w;i < m;i++) {
            cin>>u>>v>>w;
            G[u][v] = G[v][u] = w;
        }
        int mi = inf,k,id,cnt = 0;
        cin>>k;
        for(int i = 0;i < k;i++) {
            cin>>q;
            memset(vis,0,sizeof vis);
            for(int j = 0;j < q;j++) {
                cin>>a[j];
                vis[a[j]]++;
            }
            if(BFS(0)) {
                if(mi > sum) {
                    id = i+1;
                    mi = sum;
                }
                cnt++;
            }
        }
        cout<<cnt<<endl;
        cout<<id<<' '<<mi<<endl;
    }
  • 相关阅读:
    分布式算法(一致性Hash算法)
    浅析Postgres中的并发控制(Concurrency Control)与事务特性(上)
    PostgreSQL内核分析——BTree索引
    源码安装postgresql数据库
    QEMU漏洞挖掘
    mysql远程连接数据库
    C++学习之路(十一):C++的初始化列表
    搭建本地git服务器
    C++面试常见问题
    SkipList 跳表
  • 原文地址:https://www.cnblogs.com/R1ST/p/14055960.html
Copyright © 2020-2023  润新知