首页 > 其他分享 >「JOI 2017 Final」足球

「JOI 2017 Final」足球

时间:2024-10-17 20:22:49浏览次数:1  
标签:get int 运球 pla push JOI 2017 Final dis

题目询问两个点之间的对小代价,自然想到最短路。

我们发现当球在同一个点上的时候其实状态是不一样的。

如果是一个球员运球到这个点,那么可以向四个方向运球。但是如果是这个球在踢球的过程中,是改变不了方向的。

所以需要把一个点拆成五个点,分别表示在运球,向上,下,左,右踢球。

连边有以下几种:

运球点向相邻的运球点连双向边,边权为 \(C\)。

四个踢球点分别与相邻对应的点连单向边(例如向左踢球连左边点拆出来的向左踢球),边权为 \(A\)。

考虑踢球与运球之间的转换。首先运球点连单向边到踢球点,因为疲劳度计算中有一个常数 \(B\),所以边权为 \(B\)。

最后是四个踢球点到运球点,需要最近的球员跑过来,所以用 \(BFS\) 预处理一下每个点离最近的球员的距离 \(dis\),连单向边,边权为 \(dis\times C\)。

解释一下为什么最后一种连边是对的。因为题目中球员跑动和运球的疲劳度都是 \(C\),不存在一个球员去接两次球的情况,因为直接带球过去肯定不劣。

建完边跑最短路就行。

有一些小点要注意,横纵坐标从零开始,所以其实可以认为 \(n,m\le 501\),不要开小空间。

还有由于是 \(AT\) 的题,行末要输出一个换行。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=260000;
const int MAXN=5*N;
const int INF=1e18;
int dis[N],ans[MAXN];
struct node{
    int to,val;
};
vector<node> v[MAXN];
int n,m;
int a,b,c;
int man_what_can_i_say;
bool vis[N];

struct stu{
    int s,t;
}q[N];

int get_pla(int x,int y){
    return (x-1)*m+y;
}

inline int read(){
    char ch=getchar();int x=0;bool f=false;
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=true;
    for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
    if(f) x=-x;
    return x;
}

struct nnd{
    int pla,val;
    bool operator<(const nnd &aa)const{
        return val>aa.val;
    }
};
priority_queue<nnd> qe;

void bfs(){
    while(qe.size()){
        nnd x=qe.top();
        //cout<<x.pla<<" "<<x.val<<"\n"; 
        qe.pop();
        int i=x.pla/m,j=x.pla%m;
        i++;
        if(!j) j=m,i--;
        //cout<<"shit: "<<i<<" "<<j<<"\n";
        if(i>1 && !vis[get_pla(i-1,j)]){
            vis[get_pla(i-1,j)]=true;
            dis[get_pla(i-1,j)]=x.val+c;
            qe.push({get_pla(i-1,j),dis[get_pla(i-1,j)]});
        }
        if(i<n && !vis[get_pla(i+1,j)]){
            vis[get_pla(i+1,j)]=true;
            dis[get_pla(i+1,j)]=x.val+c;
            qe.push({get_pla(i+1,j),dis[get_pla(i+1,j)]});
        }
        if(j>1 && !vis[get_pla(i,j-1)]){
            vis[get_pla(i,j-1)]=true;
            dis[get_pla(i,j-1)]=x.val+c;
            qe.push({get_pla(i,j-1),dis[get_pla(i,j-1)]});
        }
        if(j<m && !vis[get_pla(i,j+1)]){
            vis[get_pla(i,j+1)]=true;
            dis[get_pla(i,j+1)]=x.val+c;
            qe.push({get_pla(i,j+1),dis[get_pla(i,j+1)]});
        }
    }
}

void init(){
    n=read(),m=read();
    n++,m++;
    a=read(),b=read(),c=read();
    man_what_can_i_say=read();
    for(int i=1;i<=n*m;i++) dis[i]=INF;
    for(int i=1;i<=man_what_can_i_say;i++){
        q[i].s=read(),q[i].t=read();
        q[i].s++,q[i].t++;
        vis[get_pla(q[i].s,q[i].t)]=true;
        dis[get_pla(q[i].s,q[i].t)]=0;
        qe.push({get_pla(q[i].s,q[i].t),0});
    }
    bfs();
}

void pre(){
    /*for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cout<<dis[get_pla(i,j)]<<" ";
        }
        cout<<"\n";
    }*/
    int plus=get_pla(n,m);
    //cout<<"plus: "<<plus<<"\n";
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int now=get_pla(i,j);
            int up,nowu,down,nowd,lef,nowl,right,nowr;
            up=now+plus,down=up+plus,lef=down+plus,right=lef+plus;
            nowu=get_pla(i-1,j),nowd=get_pla(i+1,j),nowl=get_pla(i,j-1),nowr=get_pla(i,j+1);
            v[now].push_back({up,b});
            v[now].push_back({down,b});
            v[now].push_back({lef,b});
            v[now].push_back({right,b});
            v[up].push_back({now,dis[now]});
            v[down].push_back({now,dis[now]});
            v[lef].push_back({now,dis[now]});
            v[right].push_back({now,dis[now]});
            /*if(i==2 && j==2){
                cout<<nowu<<" "<<nowd<<" "<<nowl<<" "<<nowr<<"\n";
            }*/
            if(i>1){
                int cha=nowu-now;
                v[now].push_back({now+cha,c});
                v[up].push_back({up+cha,a});
            }
            if(i<n){
                int cha=nowd-now;
                v[now].push_back({now+cha,c});
                v[down].push_back({down+cha,a});
            }
            if(j>1){
                int cha=nowl-now;
                v[now].push_back({now+cha,c});
                v[lef].push_back({lef+cha,a});
            }
            if(j<m){
                int cha=nowr-now;
                v[now].push_back({now+cha,c});
                v[right].push_back({right+cha,a});
            }
        }
    }
}

void dij(){
    for(int i=1;i<=5*n*m;i++){
        ans[i]=INF;
    }
    //cout<<1<<"\n";
    priority_queue<nnd> que;
    que.push({get_pla(q[1].s,q[1].t),0});
    ans[get_pla(q[1].s,q[1].t)]=0;
    int used=0;
    while(que.size()){
        //cout<<que.size()<<"\n";
        nnd x=que.top();
        //cout<<x<<"\n";
        que.pop();
        for(int i=0;i<v[x.pla].size();i++){
            used++;
            int to=v[x.pla][i].to;
            //cout<<"to: "<<to<<"\n";
            if(ans[to]>ans[x.pla]+v[x.pla][i].val){
                ans[to]=(ans[x.pla]+v[x.pla][i].val);
                que.push({to,ans[to]});
            }
        }
    }
    //cout<<"used: "<<used<<"\n";
    return;
}

signed main(){
    init();
    //cout<<"shit"<<"\n";
    pre();
    //cout<<"fuck"<<"\n";
    dij();
    //cout<<"caonima"<<"\n";
    int ot=INF;
    int plus=get_pla(n,m),pla=get_pla(q[man_what_can_i_say].s,q[man_what_can_i_say].t);
    //cout<<pla<<" "<<plus<<"\n";
    ot=min(ot,ans[pla]);
    ot=min(ot,ans[pla+plus]);
    ot=min(ot,ans[pla+2*plus]);
    ot=min(ot,ans[pla+3*plus]);
    ot=min(ot,ans[pla+4*plus]);
    cout<<ot<<"\n";
    return 0;
}

标签:get,int,运球,pla,push,JOI,2017,Final,dis
From: https://www.cnblogs.com/wangwenhan/p/18473000

相关文章

  • 知名服务-Samba服务漏东(CVE-2017-7494)
    Samba服务漏动原理说明CVE-2017-7494是一个Samba服务中的严重远程代码执行漏动,影响了Samba3.5.0至4.6.4/4.5.10/4.4.14之间未打补丁的版本。该漏动允许远程公鸡者在受影响的Samba服务器上执行任意代码,只要他们能够向SMB服务写入文件。公鸡者可以通过向Samba服务器上传一个特制的共......
  • Python join()函数使用详解
    在Python中,join()函数是字符串的一个方法,用于将一个可迭代对象(如列表)中的元素连接成一个字符串。join()函数的语法如下:string.join(iterable)其中,string是连接中的字符串,iterable是要连接的可迭代对象。下面是join()函数的使用示例:#连接列表中的元素my_list=['Hello',......
  • [题解]P3952 [NOIP2017 提高组] 时间复杂度
    P3952[NOIP2017提高组]时间复杂度我们把循环的嵌套关系看做树形结构,梳理一下\(3\)种情况:直接跳过当前子树:\(x,y\in\mathbb{N}\),且\(x>y\)。\(x=\tt{"n"},y\in\mathbb{N}\)。不跳过,并在处理完所有子节点后追加\(n\)的时间复杂度:\(x\in\mathbb{N},y=\tt{"n"}\)。......
  • c++如何使用pthread_join函数配合pthread_create函数来创建和等待线程完成,实现线程同
    在C++中,pthread_create 和 pthread_join 是POSIX线程库(pthread)的一部分,用于创建和管理线程。pthread_create 用于创建一个新的线程,而 pthread_join 用于等待一个线程的执行完成,从而实现线程同步与控制。基本步骤使用 pthread_create 函数创建一个线程。线程的工作由......
  • [TJOI2018] 游园会 题解
    T7[TJOI2018]游园会只能说是道有意思的好题。一般来说遇到这种题我们想到的都会是设\(f_{i,\dots}\)表示长度为\(i\),然后后面跟一堆状态的情况。此题需要我们满足两个条件:LCS的长度;不能出现\(\texttt{NOI}\)的子串。第二个限制我们可以通过状态设计来解决,但第一个......
  • 【多线程奇妙屋】“线程等待” 专讲,可不要只会 join 来线程等待哦, 建议收藏 ~~~
    本篇会加入个人的所谓鱼式疯言❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言而是理解过并总结出来通俗易懂的大白话,小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.......
  • 一张图带你了解.NET终结(Finalize)流程 ----续
    接上文https://www.cnblogs.com/lmy5215006/p/18456380评论区精彩,大佬深入讨论了C#的Finalize最佳实践,感觉有必要整理下来,拓展阅读,开拓眼界。GC类中几个非常重要的APIGC.ReRegisterForFinalize顾名思义,再次注册一个已经注册过的可终结对象。其底层实现逻辑与常规的终结注册......
  • 保姆级教程下载finalshell以及连接云服务器基础的使用教程
    废话不多说,我们直接进行安装一、软件下载下载地址:FinalShellSSH工具,服务器管理,远程桌面加速软件,支持Windows,macOS,Linux,版本4.5.10,更新日期2024.9.26-FinalShell官网(hostbuf.com)https://www.hostbuf.com/t/988.html点击链接进行下载下载完之后 打开文......
  • [TJOI2019] 甲苯先生的字符串 题解
    T2[TJOI2019]甲苯先生的字符串矩阵乘法优化DP,所以一般来说这种DP都不怎么难。30pts的DP是裸的:设\(f_{i,j}\)为前\(i\)位、最后一位是\(j\)的方案数,则有转移方程:\[f_{i,j}=\sum_{k=0}^{25}f_{i-1,k}\landk\nej\]想要矩阵优化,我们想到构造答案矩阵:\[\mathit{an......
  • JFinalcms代码审计
    JFinalCms是开源免费的JAVA企业网站开发建设管理系统,极速开发,动态添加字段,自定义标签,动态创建数据库表并crud数据,数据库备份、还原,动态添加站点(多站点功能),一键生成模板代码。环境布置:IDEA打开项目,等待maven加载好。使用phpstudy集成的mysql5.7数据库即可,导入JFinalCMS.sql数据......