AOJ : 0530 - ぴょんぴょん川渡り (Pyon-Pyon River Crossing)

問題概要

http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=0530&lang=jp
日本語の問題文があるので省略です

アルゴリズム

ジャンプの回数制限がなければ、動的計画法で簡単に実装ができると思います。
今回は、ジャンプの回数制限があったため、動的計画法だと実装しづらいと思い、ダイクストラ法で書きました。
ここでは、次の値を持たせたクラスを作成し、ダイクストラ法で解きました。

  • 現在の x 座標
  • 現在の y 座標
  • 残りのジャンプ回数
  • 現在の危険度

プログラム

import java.util.*;
import java.awt.Point;

public class Main{
  public static void main(String[] args){
    Scanner sc = new Scanner(System.in);

    while(true){
      int n = sc.nextInt();
      int m = sc.nextInt();
      if(n == 0 && m == 0) break;

      ArrayList<ArrayList<Point>> map = new ArrayList<ArrayList<Point>>();
      for(int i=0;i<n;i++){
        ArrayList<Point> tmp = new ArrayList<Point>();
        int k = sc.nextInt();
        for(int j=0;j<k;j++){
          tmp.add(new Point(sc.nextInt()-1,sc.nextInt()));
        }
        map.add(tmp);
      }

      PriorityQueue<State> open = new PriorityQueue<State>();
      HashSet<State> closed = new HashSet<State>();
      for(int i=0;i<2;i++){
        if(m < i) continue;
        for(Point p : map.get(i)){
          State nst = new State(p.x,i,p.y,m-i,0);
          open.add(nst);
        }
      }

      State ans = null;

      while(!open.isEmpty()){
        State st = open.poll();
        if(closed.contains(st)) continue;
        closed.add(st);

        if(st.y == n){
          ans = st;
          break;
        }

        open.addAll(st.nexts(map));
      }

      System.out.println(ans.cost);
    }
  }
}

class State implements Comparable<State>{
  int x,y,d,rem,cost;

  State(int x,int y,int d,int rem,int cost){
    this.x = x;
    this.y = y;
    this.d = d;
    this.rem = rem;
    this.cost = cost;
  }

  public List<State> nexts(ArrayList<ArrayList<Point>> map){
    List<State> sts = new ArrayList<State>();

    for(int i=1;i<=2;i++){
      //向こう岸についた
      if(y + i >= map.size()){
        //1行とばしできない場合以外とべる
        if(i == 1 || i == 2 && rem > 0){
          sts.add(new State(0,map.size(),0,0,cost));
        }
        continue;
      }

      //1行とばしできないから終了
      if(i == 2 && rem == 0) break;

      for(Point p : map.get(y+i)){
        sts.add(new State(p.x,y+i,p.y,rem-(i-1),cost+(d+p.y)*Math.abs(x-p.x)));
      }
    }

    return sts;
  }

  public int compareTo(State st){
    return this.cost - st.cost;
  }

  public boolean equals(Object o){
    State st = (State)o;
    return x == st.x && y == st.y && rem == st.rem;
  }

  public int hashCode(){
    return rem * 1000000 + x * 1000 + y;
  }

  public String toString(){
    return String.format("[(%d,%d),c:%d,r:%d]",x,y,cost,rem);
  }
}