原题题面看不懂的可以看下面的\(CJ\)版中文题面












$
$
\(CJ\)版:






$
$
这道题是\(JOI\)的\(T4\),放到联赛大概就是\(Day2,T3\)的难度
$
$
\(5\)分:
这一档分就是一个分类讨论,因为\(N=2\)
一共有\(3\)种情况可以出现最优解:

  1. \(1\)带球跑到\(2\),\(ans=C*(\left|h1-h2\right|+\left|w1-w2\right|)\)
  2. \(1\)带球纵向跑到与\(2\)齐平,踢球,\(ans=C*\left|h1-h2\right|+A*\left|w1-w2\right|+B\)
  3. \(1\)带球横向跑到与\(2\)齐平,踢球,\(ans=C*\left|w1-w2\right|+A*\left|h1-h2\right|+B\)

另外\(30\)分:
\(A=0\),也就是说踢球不取决于距离,踢球的花费完全取决于踢球的次数。
所以这里有两个结论,为了达到最优解,一个人不会踢球两次,一个人不会跑到其他地方去捡球来踢,这个结论画几个图就能够看出来,就不证明了。
那么整个过程就可以简化成:一个人带球跑,踢球,另一人接球,带球,再踢球。。。
这样就可以通过这个求出一个点到另一个点的最小花费,最后跑个最短路就可以求出来

\(100\)分:
这一问没有了\(A=0\)的条件,不过没有关系,上面的结论依然能用,一个人不会踢球两次。
而且这一问的\(N\)比较大,所以不可能直接对运动员进行处理。
然后我们就来想一下其他的做法。满数据的\(H\),\(W\)都比较小,我们可以把对运动员的处理换成直接对网格的处理。
设\(a[x][y]\)为步行到\((x,y)\)这个点的最小花费,这个可以\(bfs\)处理出来。
设\(ans[x][y][k]\),为在\((x,y)\)这个点时的几个状态的最小疲劳值,当\(0\le k\le3\)时,表示球从\(k\)方向滚到\((x,y)\)的最小疲劳值;当\(k=4\)时,表示运动员在\((x,y)\)持球的最小疲劳值。
那么具体怎么转移呢?
对于一个\(k=4\)的状态,它可以这样转移:

  1. 向各个方向走一格,\(ans[x'][y'][4]=ans[x][y][4]+C\);
  2. 向各个方向踢出球,\(ans[x][y][k']=ans[x][y][4]+B\);

对于一个\(k!=4\)的状态,它可以这样转移:

  1. 继续向前滚,\(ans[x'][y'][k]=ans[x][y][k]+A\);
  2. 一个运动员跑过来持球,\(ans[x][y][4]=ans[x][y][k]+C*a[x][y]\);

这个算法可以通过\(Dij\)来实现,最终的答案就是\(ans[hn][wn][4]\)。

时间复杂度:\(O(HW*logHW)\)
$
$

//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define inf (1e17)
#define ll long long
#define il inline
#define RG register
using namespace std;
il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while( ( ch<'0' || ch>'9' ) && ch!='-' ) ch=getchar();
  if( ch=='-' ) q=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; }
il void File(){freopen("soccer.in","r",stdin); freopen("soccer.out","w",stdout);}

int h,w,n;
ll A,B,C;
ll a[540][540];
ll dis[50000010];
int H[1000010],W[1000010];
int qh[1000010],qw[1000010];
bool vis[540][540],v[50000010];
int dh[]={0,-1,0,1},dw[]={-1,0,1,0};

struct heap{
#define fa (x>>1)
#define ls (x<<1)
#define rs (x<<1|1)

  int b[50000010],id[50000010],len;

  il int top(){ return b[1]; }

  il void push(RG int u){
    if(!id[u]) id[u]=++len,b[len]=u; RG int x=id[u];
    while(fa){
      if(dis[b[x]]>=dis[b[fa]]) break;
      swap(b[x],b[fa]),id[b[x]]=x,id[b[fa]]=fa,x=fa;
    }
    return;
  }

  il void pop(){
    id[b[1]]=0,b[1]=b[len--]; if (len) id[b[1]]=1; RG int x=1,son;
    while(ls<=len){
      son=(rs<=len && dis[b[rs]]<dis[b[ls]]) ? rs : ls;
      if(dis[b[x]]<=dis[b[son]]) break;
      swap(b[x],b[son]),id[b[x]]=x,id[b[son]]=son,x=son;
    }
    return;
  }

#undef fa
#undef ls
#undef rs
}que;

il void init(){
   h=gi(),w=gi(),A=gi(),B=gi(),C=gi(),n=gi();
   for(RG int i=0;i<n;i++){
      H[i]=gi(),W[i]=gi();
      if(!vis[H[i]][W[i]])
         vis[H[i]][W[i]]=1;
      else continue;
   }
   for(RG int i=0;i<=h;i++)
      for(RG int j=0;j<=w;j++)
         a[i][j]=inf;
   RG int hd=0,tl=0;
   for(RG int i=0;i<=h;i++)
      for(RG int j=0;j<=w;j++)
         if(vis[i][j]){ a[i][j]=0;
            qh[tl]=i,qw[tl++]=j;
         }
   while(hd<tl){
      RG int x=qh[hd],y=qw[hd];
      for(RG int i=0;i<4;i++){
         RG int xx=x+dh[i],yy=y+dw[i];
         if(xx<0||xx>h||yy<0||yy>w) continue;
         if(a[xx][yy]!=inf) continue;
         a[xx][yy]=a[x][y]+1;
         qh[tl]=xx,qw[tl++]=yy;
      }
      hd++;
   }
}

il void work(){
   for(RG int i=0;i<=h;i++)
      for(RG int j=0;j<=w;j++)
         for(RG int k=0;k<=4;k++)
            dis[i*5000+j+k*10000000]=inf;
   RG int t=H[0]*5000+W[0]+40000000;
   dis[t]=0; que.push(t);
   while(que.len){
      RG int q=que.top();que.pop();
      if(v[q]) continue; v[q]=1;
      RG ll c=dis[q];
      RG int dir=q/10000000;q%=10000000;
      RG int x=q/5000,y=q%5000;
      if(dir==4){
         for(RG int i=0;i<4;i++){
            RG int xx=x+dh[i],yy=y+dw[i];
            if(xx<0||xx>h||yy<0||yy>w) continue;
            RG int t=xx*5000+yy+40000000;
            if(c+C<dis[t]){ dis[t]=c+C; que.push(t); }
         }
         for(RG int i=0;i<4;i++){
            RG int t=x*5000+y+10000000*i;
            if(c+B<dis[t]){ dis[t]=c+B; que.push(t); }
         }
      }
      else{
         RG int t=x*5000+y+40000000;
         if(c+C*a[x][y]<dis[t]){
            dis[t]=c+C*a[x][y]; que.push(t);
         }
         RG int xx=x+dh[dir],yy=y+dw[dir];
         if(xx<0||xx>h||yy<0||yy>w) continue;
         t=xx*5000+yy+10000000*dir;
         if(c+A<dis[t]){ dis[t]=c+A; que.push(t); }
      }
   }
   printf("%lld\n",dis[H[n-1]*5000+W[n-1]+40000000]);
}

int main(){ File(); init(); work(); return 0; }

(没事干写手写堆来玩玩)

[JOI2017] サッカー (Soccer)的更多相关文章

  1. UVA 10194 Football (aka Soccer)

     Problem A: Football (aka Soccer)  The Problem Football the most popular sport in the world (america ...

  2. [JOI2017/2018]美術展

    [JOI2017/2018]美術展 题目大意: 有\(n(n\le5\times10^5)\)个物品,每个物品有两个属性:尺寸\(A_i\)和收益\(B_i\).从中选取一个子集,总收益为\(\sum ...

  3. D - Football (aka Soccer)

    Football the most popular sport in the world (americans insist to call it "Soccer", but we ...

  4. 每日英语:A Chinese Soccer Club Has Won Something!

    A 1-1 tie at home was sufficient for Guangzhou Evergrande to clinch the Asian Champions League title ...

  5. CodeChef CHEFSOC2 Chef and Big Soccer 水dp

    Chef and Big Soccer   Problem code: CHEFSOC2 Tweet     ALL SUBMISSIONS All submissions for this prob ...

  6. codechef May Challenge 2016 CHSC: Che and ig Soccer dfs处理

    Description All submissions for this problem are available. Read problems statements in Mandarin Chi ...

  7. 【codeforces 752F】Santa Clauses and a Soccer Championship

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  8. UVALive 5111 Soccer Teams (动态规划)

    题意:给指定数量的数字“1”,“2”,“3”……,“9”.用所有这些数字加上任意个0组成一个数,要求数能被11整除,且数的位数尽量小. 能被11整除的数有一个特点,奇数位数字之和与偶数位之和的差为11 ...

  9. UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】

    题目分析: 好像跑得很快,似乎我是第一个启发式合并的. 把玩具看成区间.首先很显然如果有两个玩具的进出时间有$l1<l2<r1<r2$的关系,那么这两个玩具一定在不同的栈中间. 现在 ...

随机推荐

  1. Ionic App ActionSheet布局问题

    使用 $ionicActionSheet的时候界面不像Ihpnoe手机那样显示的整齐,但是在电脑浏览器里面却是好的,原因还是Ionic自带css的问题,网上的答案是ionic.min.css/ioni ...

  2. 【JVM.3】虚拟机性能监控与故障处理工具

    一.概述 经过前面两章对于虚拟机内存分配与回收技术各方面的介绍,相信读者已经建立了一套比较完整的理论基础.理论总是作为指导实践的工具,能把这些执行应用到实际工作中才是我们的最终目的.接下来我们会从实践 ...

  3. 将 C# 枚举序列化为 JSON 字符串 基础理论

    该转换过程需要引用 Newtonsoft.JSON,这其中的转换过程还是蛮有意思的. 一.定义枚举 /// <summary> /// 托寄物品枚举 /// </summary> ...

  4. Dubbo(四) Dubbo-Admin项目 Dubbo管理台

    前言 在dubbo项目中,有注册中心,消费者,提供者就足以构成一个完整的项目了.但是仅仅有这三个角色,很难对整个项目状态有直观的了解,以及对项目操作. 因此早有前辈对此原因作出了贡献——一个通用的du ...

  5. Jenkins日常运维笔记-重启数据覆盖问题、迁移、基于java代码发版(maven构建)

    之前在公司机房部署了一套jenkins环境,现需要迁移至IDC机房服务器上,迁移过程中记录了一些细节:1)jenkins默认的主目录放在当前用户家目录路径下的.jenkins目录中.如jenkins使 ...

  6. Docker网络解决方案 - Weave部署记录

    前面说到了Flannel的部署,今天这里说下Docker跨主机容器间网络通信的另一个工具Weave的使用.当容器分布在多个不同的主机上时,这些容器之间的相互通信变得复杂起来.容器在不同主机之间都使用的 ...

  7. 查看服务器系统资源(cpu,内容)利用率前几位的进程的方法

    在日常运维工作中,我们经常需要了解服务器上的系统资源的使用情况,要清楚知道一些重要进程所占的资源比例.这就需要熟练掌握下面几个命令的使用: 1)查看占用CPU最高的5个进程 # ps aux | so ...

  8. getUserMedia API及HTML5 调用摄像头和麦克风

    getUserMedia API简介 HTML5的getUserMedia API为用户提供访问硬件设备媒体(摄像头.视频.音频.地理位置等)的接口,基于该接口,开发者可以在不依赖任何浏览器插件的条件 ...

  9. Python-列表-9

    列表: Why: 我们现在已经学过的数据类型有:数字,布尔值,字符串,大家都知道数字主要用于计算,bool值主要是条件判断,只有字符串可以用于数据的存储,这些数据类型够用么?对于一门语言来说,肯定是不 ...

  10. 牛客多校第二场A run(基础DP)

    链接:https://www.nowcoder.com/acm/contest/140/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言2621 ...