CSP 201903-5 317号子任务 暴力30分+优化100分

原题链接CSP 201903-5 317号子任务

1.下面是30分的暴力代码,仅仅使用常规的未优化的Dijkstra算法做的

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int MAX=10010;
const int INF=1e8;

int n,m,k;
int f[MAX];
struct  node
{
    int v,w;
    node(int _v,int _w)
    {
        v=_v;
        w=_w;
    }
};
vector<int> x[MAX];
vector<node> g[MAX];
int d[MAX];
int vis[MAX];
void dijk(int s)
{
    fill(d,d+MAX,INF);
    memset(vis,0,sizeof(vis));
    d[s]=0;
    for(int i=1;i<=n;i++)
    {
        int u=-1;
        int MIN=INF;
        for(int j=1;j<=n;j++)
        {
            if(vis[j]==0 && d[j]<MIN)
            {
                u=j;
                MIN=d[j];
            }
        }
        if(u==-1)
            return ;
        vis[u]=1;
        for(int j=0;j<g[u].size();j++)
        {
            int v=g[u][j].v;
            if(vis[v]==0 && d[u]+g[u][j].w<d[v])
            {
                d[v]=d[u]+g[u][j].w;
            }
        }
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>f[i];
    }
    while(m--)
    {
        int u,v,w;
        cin>>u>>v>>w;
        g[u].push_back(node(v,w));
        g[v].push_back(node(u,w));
    }
    for(int i=1;i<=n;i++)
    {
        dijk(i);
        ll sum=INF;
        for(int j=1;j<=n;j++)
        {
            if(f[j]==1 && d[j]!=INF)
                x[i].push_back(d[j]);
        }
        sort(x[i].begin(),x[i].end());
        ll tmp=0;
        if(x[i].size()>=k)
        {
            for(int j=0;j<k;j++)
            {
                tmp+=x[i][j];
            }
        }
        else
        {
            for(int j=0;j<x[i].size();j++)
            {
                tmp+=x[i][j];
            }
        }
        sum=min(sum,tmp);
        cout<<sum<<endl;
    }
    return 0;
}

在这里插入图片描述
2.下面是100分的优化代码,使用优化过的优先队列+Dijkstra算法做的,有一点需要注意,做题的时候需要把握数据范围的“魅力”,由上图可知,对于60%的数据,保证行星发动机的数量与k相同,这点很重要,我开始仅仅只优化过了“优先队列+Dijkstra算法”,后面对每一个点计算他与K个行星发动机的最短距离,交上去还是30分,于是我把后面的计算距离“由遍历所有节点到行星发动机的距离改为遍历行星发动机结点到每个结点的距离”,即for循环里的遍历由1e4变为了1e2,极大的减少了计算过程,不过我这样的想法本来是只想着通过60%的数据,没想到100分了
在这里插入图片描述

以下是满分代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+10;
const int INF=0x3f3f3f3f;
#define ll long long

int n,m,k;
struct Node
{
    int v;
    int w;
    Node(int _v,int _w)
    {
        v=_v; w=_w;
    }
    friend bool operator < (const Node& a,const Node& b)
    {
        return a.w>b.w;
    }
};
int type[N];
vector<Node> adj[N];
vector<int> dis[N];

ll d[N];
bool vis[N];
priority_queue<Node> q;

void dijkstra(int s)
{
    fill(d,d+N,INF);
    memset(vis,0,sizeof(vis));
    d[s]=0;
    q.push(Node(s,d[s]));
    while(!q.empty())
    {
        Node x=q.top();
        q.pop();
        int u=x.v;
        if(vis[u]==1) continue;
        vis[u]=1;
        for(int i=0;i<adj[u].size();i++)
        {
            int v=adj[u][i].v;
            if(vis[v]==0 && d[u]+adj[u][i].w<d[v])
            {
                d[v]=d[u]+adj[u][i].w;
                q.push(Node(v,d[v]));
            }
        }
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) cin>>type[i];
    for(int i=0;i<m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        adj[u].push_back(Node(v,w));
        adj[v].push_back(Node(u,w));
    }
    for(int i=1;i<=n;i++)
    {
        if(type[i])
        {
            dijkstra(i);
            for(int j=1;j<=n;j++)
            {
                if(d[j]!=INF) dis[j].push_back(d[j]);
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        sort(dis[i].begin(),dis[i].end());
        ll res=INF,tmp=0;
        if(dis[i].size()<=k)
        {
            tmp=accumulate(dis[i].begin(),dis[i].end(),0);
        }
        else tmp=accumulate(dis[i].begin(),dis[i].begin()+k,0);
        cout<<min(res,tmp)<<endl;
    }
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用: 这是2020年CSP-J入门单项选择题解析,解析明白,一看就懂。整理不易,文章出错评论区说,看见必改。请一键三连,给个五星好评。小编那么拼,给个赞再撤┗|`O′|┛ 嗷~~。 引用: 子任务中显示测试点2正确个数为0,因此,可以用如下方法,骗到10。以下是一个C++的代码示例: #include <iostream> using namespace std; int main() { int n; cin >> n; for (int i = 0; i < n; i++) { cout << "No" << endl; } return 0; } 以上代码会输出n个"No",可以通过测试点2并获得10。 引用: 这是一个使用数组和栈实现的C++代码示例: #include <iostream> #include <stack> using namespace std; int main() { char a[100]; int n; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } for (int i = 0; i < n; i++) { int num; //运算数 char oper; //运算符 int sum = 0; for (int j = 0; j < 7; j++) { if (j % 2 == 0) num[j / 2] = a[i][j] - 48; //0的ASSIC码为48 else oper[j / 2] = a[i][j]; } stack<int> snum; stack<char> soper; snum.push(num); for (int i = 0; i < 3; i++) { if (oper[i] == 'x' ||oper[i] == '/') { int temp = snum.top(); snum.pop(); if (oper[i] == 'x') snum.push(temp * num[i + 1]); else snum.push(temp / num[i + 1]); } else if (oper[i] == '-') { snum.push(-num[i + 1]); soper.push(oper[i]); } else { snum.push(num[i + 1]); soper.push(oper[i]); } } sum = snum.top(); snum.pop(); for (int i = 0; i < soper.size(); i++) { sum += snum.top(); snum.pop(); } if (sum == 24) cout << "Yes" << endl; else cout << "No" << endl; } } 以上代码实现了一个解析给定算术表达式是否等于24的程序。 问题:请告诉我,csp201903-2是什么? csp201903-2是一个CSP(全国计算机科学与技术专业资格考试)的题目编号,表示该题是2019年3月份的第2道题目。具体题目内容需要查阅相关资料来获取。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [2020年CSP-J入门单项选择题解析](https://download.csdn.net/download/sjy100401/88234366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [CSP 201903-2 二十四点 (C++)](https://blog.csdn.net/qq_39876147/article/details/117091994)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [CSP201903-2二十四点](https://blog.csdn.net/weixin_43074474/article/details/101128023)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值