2019年中南大学机试题d题

2019年中南大学机试题D题

题目链接

题目描述

CSU镇上有n个商店,n个商店有m条双向小路相连,在这n个商店里共有k种不同商品,每个商店只有一种商品,每条路的权重都为1。现问你从每个商店出发,买够k种商品中的s种商品所需的最小代价,每个商店可以同时派出多个人买不同商品,买够即可。

输入

输入包含多组测试用例。

对于每一组输入包含四个数字n ,m, k,s (1<=n<=m<=1e5 , 1<=s<=k<=min(n,100))

分别代表商店数,小路数,商品种数,需要的商品数。

接下来n个数 a1,a2...an (1<=ai<=k),ai代表第i个商店的商品编号。

接下来m行小路(u,v),u≠v,代表商店u和v之间有小路连接。

输出

输出n个数字,第i个数字代表从商店i出发买够s种商品所需的最小代价。

样例输入

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

样例输出

2 2 2 2 3
1 1 1 2 2 1 1

题目思路

就是道bfs题,但是和一般的BFS不同。这道题要用多源BFS。题目求的是每个商店购买s中物品的代价。每个商店都去求一遍BFS。但是你会发现n太大了。会超时。n>>k的,可以换个思考,对物品进行BFS。就是求每个物品的商店到各个商店的最小步数。比求各个商店到每个物品的商店的步数花费的时间要小的很多。

上代码

#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXM = 1e5+5;
int shop[MAXM];
vector<int> goods[MAXM];
int ans[MAXM][200];
void bfs(int index, int n)
{
    queue<int> q;
    int now;
    for(int i = 1; i <= n; i++)
        if(shop[i] == index)
        {
            // 如果该商店的物品就是要搜索的物品则代价为0
            ans[i][index] = 0;
            // 从拥有该物品的商店开始搜索
            q.push(i);
        }
    while(!q.empty())
    {
        now = q.front();
        for(int i = 0; i < goods[now].size(); i++)
        {
            // 搜素与该商店有通路的店子
            int nex = goods[now][i]; // 现在搜索到的商店编号
            if(ans[nex][index] == -1)
            {
                // 该商店还没被搜索到, 则购买index物品的代价为上一步的代价+1
                ans[nex][index] = ans[now][index] +  1;
                q.push(nex); // 把此商店加入过搜索队列之中
            }
        }
        q.pop();
    }
}
int main()
{
    int n, m, k, s, u, v, an;
    while(scanf("%d %d %d %d", &n, &m, &k, &s) != EOF)
    {
        for(int i = 1; i <= n; i++)
        {
            goods[i].clear();
            scanf("%d", &shop[i]);
        }
        for(int i = 1; i <= m; i++)
        {
            scanf("%d %d", &u, &v);
            //用vector存储每个商店与其他商店的是否有
            goods[u].push_back(v);
            goods[v].push_back(u);
        }
        memset(ans, -1, sizeof(ans));
        for(int i = 1; i <= k; i++)// 求每个商店购买第i的物品所需要的代价
            bfs(i, n);
        for(int i = 1; i <= n; i++)
        {
            an = 0;
            // 我们把第i个商店购买各个物品所需要的代价排序
            //我们存数据的时候是从1开始的所以要加1
            sort(ans[i]+1, ans[i]+1+k);
            // 从中挑选代价最小的s个物品
            for(int j = 1; j <= s; j++)
                an += ans[i][j];
            printf("%d ", an);
        }
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Mrs-Jiangmengxia/p/12641522.html

时间: 2024-10-01 05:10:22

2019年中南大学机试题d题的相关文章

2016年微软机试题第一题——FontSize

题目描述:N个段落 P个页面 W的段长 H的页长 一个数组给出每个段落的字数 目标找到符合要求的最大字符大小. 难点:(1)必须根据题目的描述,给出符合条件的字符输入方案: (2)使用二分法不断逼近可选择的最大字符大小: (3)如何利用判断表达式实现取整,和选择: 重要思想:最令人迷茫的地方在于,字符和段和页面之间的关系:必须要看清他们之间的层次关系:字符分割统计出段,段统计分割出现页面.利用页面的比较产生可行的结果. 1 package shounue; 2 import java.util.

1027: 逃离迷宫(2018年中南大学研究生复试机试题)

1027: 逃离迷宫 时间限制: 1 Sec  内存限制: 128 MB提交: 611  解决: 130[提交] [状态] [讨论版] [命题人:外部导入] 题目描述 PIPI被困在一个迷宫中了!   给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,PIPI想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,PIPI可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,PIPI不能走到迷宫外面去.令人头痛的是,PIPI是个

1022: 淘金(2017年中南大学研究生复试机试题 )

1022: 淘金 时间限制: 1 Sec  内存限制: 128 MB提交: 205  解决: 75[提交] [状态] [讨论版] [命题人:外部导入] 题目描述 在一片n*m的土地上,每一块1*1的区域里都有一定数量的金子.这一天,你到这里来淘金,然而当地人告诉你,如果你挖了某一区域的金子,上一行,下一行,左边,右边的金子你都不能被允许挖了.那么问题来了:你最多能淘金多少? 输入 对于每组数据,第一行两个数n,m,表示土地的长和宽(1<=n,m<=200) 接下来n行,每行m个数,表示每个区域

1021: 机器人走迷宫(2017年中南大学研究生复试机试题 )

1021: 机器人走迷宫 时间限制: 1 Sec  内存限制: 128 MB提交: 339  解决: 71[提交] [状态] [讨论版] [命题人:外部导入] 题目描述 有一个愚蠢的机器人走进一个w*h的迷宫,迷宫里有空地和陷阱.他想要访问迷宫的每个方格,但是它很笨,只会按照指令的方向走.当机器人不能走的时候,也就是下一步会遇到陷阱.迷宫边界或者访问过的格子,它会向右转90度(顺时针旋转90度,不能访问已经访问过的方格,且在原地只转一次,移动后可获得又一次旋转机会).请问这个机器人最多可以经过多

华为的一道机试题--等式变换

华为的一道机试题 (http://blog.csdn.net/zombie_slicer/article/details/37346025) 第三题:等式变换 输入一个正整数X,在下面的等式左边的数字之间添加+号或者-号,使得等式成立. 1 2 3 4 5 6 7 8 9 = X 比如: 12-34+5-67+89 = 5 1+23+4-5+6-7-8-9 = 5 请编写程序,统计满足输入整数的所有整数个数. 输入:       正整数,等式右边的数字 输出:       使该等式成立的个数 样

华为2014机试题(一)

过几天就要进行华为的机试了,今儿临时抱抱佛脚,在网上找到2014届华为校招的机试题,琢磨了一会儿,贴出来记录下. 首先感谢一下Hackbuteer提供的题目:http://blog.csdn.net/hackbuteer1/article/details/11132567 对于第一题,字符过滤.最简单也是最直接的就是HASH.题目规定了输入序列只能为小写字符'a~z'.因此直接开辟一个大小为26的数组用于记录当前字符是否已经出现即可. 需要注意的问题: 1. hash数组记得初始化 2. pOu

2015年华为校招机试题和代码实现(分解字符串,拼音转数字,去除重复字符并排序,等式变换)

再来一套2015年的华为机试题. 第一题(60分): 按要求分解字符串,输入两个数M,N:M代表输入的M串字符串,N代表输出的每串字符串的位数,不够补0.例如:输入2,8, "abc" ,"123456789",则输出为"abc00000","12345678","90000000" 分析思路: 容易题 1.获得字符串的长度length后,判断与要输出位数N的大小,大于N的话,直接printf前N位字符,然

[华为机试真题]66.单词搜索

题目 代码 /*--------------------------------------- * 日期:2015-07-06 * 作者:SJF0115 * 题目:WordSearch * 来源:华为机试真题 -----------------------------------------*/ #include <iostream> #include <string> #include <vector> #include <stack> #include

ASPNET服务端控件练习(一个机试题)

简单记录: 模糊查询的select语句的拼写 public List<Model.Student> GetWhereStudent(string name, string sub, string isG) { List<Web.Model.Student> lt = new List<Model.Student>(); string sql = "select * from SC_Student where studentName like @n and [e