zoukankan      html  css  js  c++  java
  • USACO 2014 JAN滑雪场评级{Gold题3}

    滑雪场评级{Gold3}

    【问题描述】

       滑雪场用一个M*N(1 <= M,N <= 500)的数字矩阵表示海拔高度,每个数字表示一个范围在0 .. 1,000,000,000的高度。有些格子被指定为起点,组织者想对这些起点做难度评级。

    如果起点P点是一个难度级别为D的起点,则D必须是满足以下条件的一个最小值:

    (1)从一个格子只能滑到相邻的格子;

    (2)这两个格子的海拔差不超过D;

    (3)至少能够到达T(1 <= T <= M*N)个格子(包括起点本身)。

    【文件输入】

    第一行,三个用空格隔开的整数,分别表示M,N和T。

    接下来2.. M+1行,每行一个N个整数,表示海拔。

    接下来M+2.. 2M+1行,每行一个整数0或者1,其中1表示该格子是一个起点。

    【文件输出】

        共一行,一个整数,所有起点的难度和。

    【输入样例】

    3 5 10

    20 21 18 99 5

    19 22 20 16 17

    18 17 40 60 80

    1 0 0 0 0

    0 0 0 0 0

    0 0 0 0 1

    【输出样例】

    24

    【样例说明】

    左上角的格子是一起点,难度为4,右下角的格子是一个起点,难度为20。 

    思路:这道题原来以为只要二分再搜索就可以AC了,结果发现差的还是有点远了,只过了一个点。后来请教某大牛得知原来这题的算法主要是用最小生成树的kruskal算法,把整个图用边连接起来,边的权值等于两个点之间的高度差绝对值,然后对边进行快排,每次加入最小的一条边,当边数大于题目要求的t时,深搜整个图,此时搜到的起点的难度值即为当前加进去边的权值。下面上代码

      1 type node=record
      2  s,t,w:longint;
      3 end;
      4 
      5 var
      6 v:array[0..500000]of node;                   //v表示每条边的端点以及权值
      7 fa,size:array[0..250000]of longint;          //fa表示每个点的父节点;size表示每个连通块所包含的点的数量
      8 h:array[0..500,0..500]of longint;
      9 used,isstart:array[0..250000]of boolean;     //used表示每个点是否已经搜索过;isstart表示该点是否为起点
     10 map:array[0..250000,0..4]of longint;         //map表示每个点所连通的点
     11 n,m,kk,ss,ans:int64;                         //ss表示边的条数
     12 
     13 procedure openit;
     14  begin
     15   assign(input,'skilevel.in');assign(output,'skilevel.out');
     16   reset(input);rewrite(output);
     17  end;
     18 
     19 procedure closeit;
     20  begin
     21   close(input);close(output);
     22  end;
     23 
     24 procedure qsort(l,r:longint);
     25  var i,j,m:longint;
     26      t:node;
     27   begin
     28    i:=l;j:=r;m:=v[(l+r) div 2].w;
     29    repeat
     30     while v[i].w<m do inc(i);
     31     while v[j].w>m do dec(j);
     32     if not (i>j) then
     33      begin
     34       t:=v[i];v[i]:=v[j];v[j]:=t;
     35       inc(i);dec(j);
     36      end;
     37    until i>j;
     38    if l<j then qsort(l,j);
     39    if i<r then qsort(i,r);
     40   end;
     41 
     42 function getfather(x:longint):longint;
     43  begin
     44   if fa[x]=x then exit(x);
     45   fa[x]:=getfather(fa[x]);
     46   getfather:=fa[x];
     47  end;
     48 
     49 procedure datain;
     50  var i,j,num:longint;
     51   begin
     52    readln(n,m,kk);
     53    for i:=1 to n do
     54     begin
     55      for j:=1 to m do read(h[i,j]);
     56      readln;
     57     end;
     58    for i:=1 to n do
     59     begin
     60      for j:=1 to m do
     61       begin
     62        read(num);
     63        if num=1 then isstart[(i-1)*m+j]:=true;
     64       end;
     65      readln;
     66     end;
     67    for i:=1 to n do
     68     for j:=1 to m do
     69      begin
     70       if i<n then
     71        begin
     72         inc(ss);
     73         v[ss].s:=(i-1)*m+j;
     74         v[ss].t:=i*m+j;
     75         v[ss].w:=abs(h[i,j]-h[i+1,j]);
     76        end;
     77       if j<m then
     78        begin
     79         inc(ss);
     80         v[ss].s:=(i-1)*m+j;
     81         v[ss].t:=(i-1)*m+j+1;
     82         v[ss].w:=abs(h[i,j]-h[i,j+1]);
     83        end;
     84      end;
     85    for i:=1 to n*m do            //初始化
     86     begin
     87      fa[i]:=i;
     88      size[i]:=1;
     89     end;
     90    qsort(1,ss);                  //快排权值
     91   end;
     92 
     93 procedure dfs(pos,cur:longint);
     94  var i:longint;
     95   begin
     96    used[pos]:=true;
     97    if isstart[pos] then
     98     begin
     99      ans:=ans+cur;
    100      isstart[pos]:=false;
    101     end;
    102    for i:=1 to map[pos,0] do
    103     if not used[map[pos,i]] then dfs(map[pos,i],cur);
    104   end;
    105 
    106 procedure kruskal;                    //运用最小生成树的思想进行求解
    107  var i,j,x,y:longint;
    108   begin
    109    for i:=1 to ss do
    110     begin
    111      x:=getfather(v[i].s);
    112      y:=getfather(v[i].t);
    113      if x<>y then
    114       begin
    115        if (size[x]<kk) and (size[x]+size[y]>=kk) then dfs(x,v[i].w);
    116        if (size[y]<kk) and (size[x]+size[y]>=kk) then dfs(y,v[i].w);
    117        fa[y]:=x;
    118        size[x]:=size[x]+size[y];
    119        inc(map[v[i].s,0]);
    120        map[v[i].s,map[v[i].s,0]]:=v[i].t;
    121        inc(map[v[i].t,0]);
    122        map[v[i].t,map[v[i].t,0]]:=v[i].s;
    123       end;
    124     end;
    125   end;
    126 
    127 
    128 begin
    129  openit;
    130  datain;
    131  kruskal;
    132  writeln(ans);
    133  closeit;
    134 end.
  • 相关阅读:
    Java之List使用方法
    Java之数组遍历
    收集关于前端的一些网站、博客资源、框架、源码等 、 会持续更新哦!!!!!
    css常用代码含义
    css两列等高布局
    HTML之DocType的几种类型
    CSS实现圆角的方法
    IE6图片元素img下出现多余空白问题
    web标准常见问题整理
    好的 Web 前端年薪会有多少?
  • 原文地址:https://www.cnblogs.com/p0226/p/4074662.html
Copyright © 2011-2022 走看看