[JOYOI1510] 专家复仇 - Floyd

题目限制

时间限制 内存限制 评测方式 题目来源
1000ms 131072KiB 标准比较器 Local

题目背景

外星人完成对S国的考察后,准备返回,可他们的飞碟已经没燃料了……
S国的专家暗自窃喜……复仇的机会终于来了——他们打算敲诈外星人一大笔钱……

题目描述

S国有n个燃料基地,保存有外星人所需的全部燃料,编号分别为1,2,3,…,n,对于每个燃料基地i,都有【((i-1) mod 10)+1】吨燃料。其中,编号<=5的燃料基地两两之间都有可双向通行的路;对于其余每个燃料基地i,与(i-1),(i-3)之间,也有可双向通行的路。对于任意两燃料基地i,j,若之间有路将他们【直接】连接,则通过这条路的运费为【(i*j)mod10+(i+j)mod6+1)】(单位:元/吨)。
S国的专家要按每吨一元的价格把燃料卖给外星人,并且要它们支付运费。那么,外星人应选择把所有燃料运往那个燃料基地,才能尽可能的让S国专家失望?它们所要支付的最小费用是多少?
注:数据保证解的唯一性。

输入格式

仅有一个整数n。

输出格式

第一行:外星人所要支付的最小费用;
第二行:可供外星人选择的燃料基地的编号。

提示

样例解释:
第1-5个基地两两间有路,第6个基地与第3,5个基地间有路。当把全部燃料运到第五个基地时,总费用最少,为107.

数据范围:
对于 30%的数据,有5<N<50;
对于 60%的数据,有5<N<500;
对于100%的数据,有5<=N<700;
输出数据范围请大家自行判断。

样例数据

输入样例 #1输出样例 #1
6

107

5

 


 

 

签到题;

 


 

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n;
int dis[710][710];
int f[710], mx=1e9;
int ans;

int main()
{
    scanf("%d", &n);
    memset(dis, 0x3f, sizeof dis);
    for (register int i = 1; i <= n; i ++) dis[i][i] = 0;
    for (register int i = 1; i <= 5; i ++)
    {
        for (register int j = 1;j <= 5; j ++)
        {
            if (i == j) continue;
            dis[i][j] = dis[j][i] = (i * j) % 10 + (i + j) % 6 + 1;
        }
    }
    for (register int i = 6 ; i <= n; i ++)
    {
        int j = i - 1;
        dis[i][j] = dis[j][i] = (i * j) % 10 + (i + j) % 6 + 1;
        j = i - 3;
        dis[i][j] = dis[j][i] = (i * j) % 10 + (i + j) % 6 + 1;
    }
    for (register int i = 1; i <= n; i ++) ans += (i - 1) % 10 + 1;
    for (register int k = 1; k <= n; k ++)
        for (register int i = 1; i <= n; i ++)
            for (register int j = 1; j <= n ; j ++)
                if (i != j and j != k and k != j)
                    dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
    for (register int i = 1; i <= n; i ++)
    {
        for (register int j = 1; j <= n; j ++)
        {
            if (i == j) continue;
            f[i] += dis[i][j] * ((j - 1) % 10 + 1);
        }
        mx = min(mx, f[i]);
    }
    cout << ans + mx << endl;
    for (register int i = 1; i <= n; i ++)
    {
        if (f[i] == mx) printf("%d ", i);
    }
    return 0;
}

 

posted @ 2018-07-04 22:38  zZhBr  阅读(113)  评论(0编辑  收藏  举报