原题题面看不懂的可以看下面的\(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. kubectl客户端工具远程连接k8s集群

    一.概述 一般情况下,在k8smaster节点上集群管理工具kubectl是连接的本地http8080端口和apiserver进行通讯的,当然也可以通过https端口进行通讯前提是要生成证书.所以说k ...

  2. How to Enable TLS 1.2 on Windows Server 2008 R2 and IIS 7.5

    Nowadays there is an SSL vulnerability called POODLE discovered by Google team in SSLv3 protocol. So ...

  3. .net获取excel表的内容(OleDB方法)

    首先引用组件和命名空间 using Microsoft.Office.Interop.Excel; using System.Data.OleDb; 然后把excel上传到指定路径 上传文件方法省略 ...

  4. [Oacle][Partition]Partition操作与 Index, Global Index 的关系

    [Oacle][Partition]Partition操作与 Index, Global Index 的关系: ■ Regarding the local index and the global i ...

  5. python语言程序设计?

    1, 别说了,我还是有几分蛋疼的.女朋友..计算机..唉 2, 今天把那几个练习写完吧? 3, 这个注释有啥用最前面的?? 4, 我在学完python后必须学完C和C++并开始离散数学和线代高数等全复 ...

  6. Sql_索引分析

    「索引就像书的目录, 通过书的目录就准确的定位到了书籍具体的内容」,这句话描述的非常正确, 但就像脱了裤子放屁,说了跟没说一样,通过目录查找书的内容自然是要比一页一页的翻书找来的快,同样使用的索引的人 ...

  7. 从源码的角度看 React JS 中批量更新 State 的策略(下)

    这篇文章我们继续从源码的角度学习 React JS 中的批量更新 State 的策略,供我们继续深入学习研究 React 之用. 前置文章列表 深入理解 React JS 中的 setState 从源 ...

  8. easyUI中textbox或number的数值大小校验

    例:textbox里面,要求做两个textbox名字为(A,B),其中两个的数字大小范围是-10~10之间,之后其中A的值必须大于B所填的数字,如果输入错误,则提示出弹出框,并清空数据. <!D ...

  9. 《linux内核设计与实现》第十八章

    第十八章 调试 调试工作艰难是内核级开发区别于用户级开发的一个显著特点. 一.准备开始 1.内和调试需要什么 一个bug(大部分bug通常都不是行为可靠而且定义明确的) 一个藏匿bug的内核版本(知道 ...

  10. 20135327郭皓--Linux内核分析第八周 进程的切换和系统的一般执行过程

    第八周 进程的切换和系统的一般执行过程 一.进程切换的关键代码switch_to分析 1.进程调度与进程调度的时机分析 不同类型的进程有不同的调度需求 第一种分类: I/O-bound:频繁进行I/O ...