Cpp环境【Usaco 3.2.6】【Vijos1251】Павлов的香甜黄油

农夫John想要训练奶牛在听到铃声时前往特定牧场吃糖以制作超甜黄油。给定奶牛数量、牧场数量和牧场间的路径,找到使所有奶牛到达总距离最短的牧场。通过暴力枚举所有可能的放糖位置并计算总距离,找出最小总距离并输出。
摘要由CSDN通过智能技术生成
【问题描述】  

  农夫John发现了做出全威斯康辛州最甜的黄油的方法:把糖放在一片牧场上,他知道他所有的N只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。
  农夫John很狡猾。就像以前的巴甫洛夫,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,好让他可以在晚上挤奶。
  农夫John知道开始时,每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛所在的牧场和牧场间的路线,找出使所有牛到达的路程之和最短的牧场(他将把糖放在那)。

【输入格式】  

第 1 行: 三个数:奶牛数 N,牧场数 P,牧场间道路数 C。
第 2 行到第 N+1 行: 1 到 N 头奶牛所在的牧场号。
第 N+2 行到第 N+C+1 行: 每行有三个数:相连的牧场A、B,两牧场间距 D,当然,连接是双向的。

【输出格式】  

一行 输出奶牛必须行走的最小的距离和。

【输入样例】  

3 4 5
2
3
4
1 2 1
1 3 5
2 3 7
2 4 3
3 4 5

【输出样例】  

8

【数据范围】  

  2 <= P <= 800
  1 <= C <= 1450
  1 <= D <= 255
  1 <= N <=500

【思路梳理】  

数据规模不大,再加上没有什么其他的好办法,所以可以依次穷举所有的牧场,假设将糖放在第i个牧场,求出第i个牧场到其他所有牧场的最小距离之和。对于枚举的所有最优结果,直接取一个最小值输出即可。
给出一个伪代码方便读者理解:

void solve()
{
    依次穷举每一个牧场:
    将dist(距离)置为无穷大,
    以该牧场为出发源使用SPFA算法/Dijstra算法求出所有点到该出发源的距离dist[i]。
    将所有的距离相加,与目前最优结果进行比较。

    输出最优解
}

【Cpp代码】

#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxnum 505
#define maxn 805
#define inf 2000000005
using namespace std;
int num,p,c,dist[maxn],loca[maxnum],cnt=inf;
vector<int>g[maxn],w[maxn];
bool inq[maxn];

int SPFA(int s)//改造了一下SPFA算法,让他返回距离之和,一个漏洞是可能存在有些点不能够到达使得最小距离的加和超过了int上界
{
    int ans=0;
    memset(inq,false,sizeof(inq));
    for(int i=1;i<=p;i++)   dist[i]=inf;
    queue<int>q;
    q.push(s);
    inq[s]=true;
    dist[s]=0;

    while(!q.empty())
    {
        int i=q.front();q.pop();
        inq[i]=false;
        for(int j=0;j<g[i].size();j++)
        {
            int k=g[i][j],c=w[i][j];
            if(dist[k]>dist[i]+c)
            {
                dist[k]=dist[i]+c;
                if(!inq[k])
                {
                    inq[k]=true;
                    q.push(k);
                }
            }   
        }
    }

    for(int i=1;i<=num;i++)
        ans+=dist[loca[i]];
    return ans; 
}

int main()
{
    //freopen("in.txt","r",stdin);
    cin>>num>>p>>c;
    for(int i=1;i<=num;i++)//记录有奶牛的牧场的编号
        scanf("%d",&loca[i]);
    for(int i=1;i<=c;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        g[x].push_back(y);w[x].push_back(z);
        g[y].push_back(x);w[y].push_back(z);//建立存储结构
    }

    for(int i=1;i<=p;i++)//对于每一个牧场依次枚举,使用SPFA算法求出各点的最短距离之和
        cnt=min(cnt,SPFA(i));

    cout<<cnt;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值