zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    为什么 PCB 生产时推荐出 Gerber 给工厂?
    Fedora Redhat Centos 有什么区别和关系?
    【KiCad】 如何给元件给元件的管脚加上划线?
    MCU ADC 进入 PD 模式后出现错误的值?
    FastAdmin 生产环境升级注意
    EMC EMI 自行评估记录
    如何让你的 KiCad 在缩放时不眩晕?
    KiCad 5.1.0 正式版终于发布
    一次单片机 SFR 页引发的“事故”
    java基础之集合
  • 原文地址:https://www.cnblogs.com/R1ST/p/14055960.html
Copyright © 2011-2022 走看看