AOJ2008 Dragon Fantasy
問題リンク Dragon Fantasy
- 解法
全探索+枝刈りです。訪れた状態と最後に訪れた場所の対をノードにした幅優先だと、状態数が2^N*Nになってメモリが足りません。
探索の枝刈りの条件として、未訪問の場所のうち、1つでも訪れることができなくなった場所があったら刈ります。この枝刈りだけで通ります。
- ソース
import java.util.Scanner; //Dragon Fantasy public class AOJ2008 { int n, hx, hy, dx, dy; int[][] p; double[] r; double[][] d; double EPS = 1e-8; boolean dfs(int k, int S, double t){ if(S==(1<<n)-1)return true; for(int i=0;i<n;i++){ if(((S>>i)&1)>0)continue; if(r[i]<t+d[k][i]+EPS)return false; } for(int i=0;i<n;i++){ if(((S>>i)&1)>0)continue; if(r[i]>t+d[k][i]){ if(dfs(i, S+(1<<i), t+d[k][i]))return true; } } return false; } void run(){ Scanner sc = new Scanner(System.in); for(;;){ n = sc.nextInt(); hx = sc.nextInt(); hy = sc.nextInt(); dx = sc.nextInt(); dy = sc.nextInt(); if((n|hx|hy|dx|dy)==0)break; p = new int[n][2]; for(int i=0;i<n;i++)for(int j=0;j<2;j++)p[i][j]=sc.nextInt(); r = new double[n]; for(int i=0;i<n;i++)r[i]=Math.hypot(p[i][0]-dx, p[i][1]-dy); d = new double[n+1][n+1]; for(int i=0;i<n;i++){ d[n][i] = d[i][n] = Math.hypot(hx-p[i][0], hy-p[i][1]); for(int j=i+1;j<n;j++)d[i][j] = d[j][i] = Math.hypot(p[i][0]-p[j][0], p[i][1]-p[j][1]); } System.out.println(dfs(n, 0, 0)?"YES":"NO"); } } public static void main(String[] args) { new AOJ2008().run(); } }