poj 3460 Booksort(IDA*)

题目大意:有N(1 ≤ N ≤ 15)本书,每本与每本的高度都不一样。现在可以按照以下的办法整理书:抽出一摞书,再保持原来的顺序插进一个位置。这样的话我们称之为“一次操作”。现在你需要求出至少需要经过几次操作才能让书变成按高度升序的状态。如果需要5次或者多于5次,只需要输出“5 or more”。

解法:IDA*是一种特殊的dfs,每次dfs都设置一个阀值,一旦解的深度超出阀值就回溯。只不过IDA*加上了对当前状态的估计——一旦已经走过的步数加上估计步数超出阀值,就进行回溯。若在此阀值下无解,则迭代增加阀值,只有找到的解深度是最小的。当然,“估价函数”与实际深度越接近越好,而且应该小于等于实际深度。

这个题的估价函数很经典——因为一次操作最多改变3个值的后继值,而最终状态要求每个位置的后继值都比自己大1,因此估价函数为当前状态下每个值的后继值错误的个数除以3。

import java.util.Scanner;

public class Main{
	int h() {
		int res = 0;
		for(int i=1;i<n;i++)
			if(arr[i]+1!=arr[i+1]) res++;
		if(arr[n]!=n) res++;
		return (res+2)/3;
	}
	long hash(){
		long res=0;		
		return res;
	}
	int lim, n;
	int arr[]=new int[20];
	boolean flag;
	int dfs(int d) {
		int h = h();
		if (h == 0){
			flag=true;
			return d;
		}
		if (h + d > lim)
			return h + d;
		int temp[]=new int[n+1];
		for(int i=1;i<=n;i++)
			temp[i]=arr[i];
		int res = 1 << 28;
		for (int i = 1;i<n;i++)
			for (int j= i;j<n;j++)
				for (int k = j + 1; k <= n; k++) 
				{
					int cnt=i;
					for(int p=j+1;p<=k;p++)
						arr[cnt++]=temp[p];
					for(int p=i;p<=j;p++)
						arr[cnt++]=temp[p];
					int tp=dfs(d+1);
					if(flag)	
					  return tp;
					else
						res=Math.min(tp, res);
					cnt=i;
					for(int p=i;p<=j;p++)
						arr[cnt++]=temp[p];
					for(int p=j+1;p<=k;p++)
						arr[cnt++]=temp[p];
				}
		return res;
	}
	void astar(){
		lim=h();
		flag=false;
		while(lim<=4&&!flag)
			lim=dfs(0);
		
		if(flag)
			System.out.println(lim);
		else
			System.out.println("5 or more");
	}
	Scanner scan=new Scanner(System.in);
	void run(){
		int cas=scan.nextInt();
		while(cas-->0){
			n=scan.nextInt();
			for(int i=1;i<=n;i++)
				arr[i]=scan.nextInt();
			astar();
		}
	}

	public static void main(String[] args) {
		new Main().run();
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值