HDU ACM 2234 无题I->IDA*算法

分析:IDA*解决,借鉴大牛的启发式函数h(): 可以考虑把每一行上的数转化成相同的,或者把每一列上的数字转化成相同的,二者取最小值。

例如:

1 1 3 2

2 4 4 2

3 3 1 4

1 2 3 4

把这个矩阵转化成行合法矩阵需要的操作:第一行至少要2次,第二行也是2次, 第三行是2次,第四行是3次, 所以把矩阵转化成行相同至少要3次。

#include<iostream>
using namespace std;

int map[5][5];
int deep;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))

bool check()         //检查是否是合法状态
{
	int i,j;

	if(map[1][1]!=map[1][2])
	{
		for(i=1;i<=4;i++)
			for(j=1;j<=4;j++)
				if(map[j][i]!=map[i][i])
					return false;
	}
	else
	{
		for(i=1;i<=4;i++)
			for(j=1;j<=4;j++)
				if(map[i][j]!=map[i][i])
					return false;
	}
	return true;
}

int get_h()         //IDA*的估价函数,获取每行或每列不在合法位置的数量
{
	int r=0,c=0,i,j;

	for(i=1;i<=4;i++)         //每行
	{
		int ans=0;
		int h[5]={0};
		for(j=1;j<=4;j++) h[map[i][j]]++;
		for(j=1;j<=4;j++)ans=max(ans,h[j]);
		r=max(4-ans,r);
	}
	for(j=1;j<=4;j++)         //每列
	{
		int ans=0;
		int h[5]={0};
		for(i=1;i<=4;i++) h[map[i][j]]++;
		for(i=1;i<=4;i++)ans=max(ans,h[i]);
		c=max(4-ans,c);
	}
	return min(r,c);
}

void mov_l(int i)
{
	int j,t;

	t=map[i][1];
	for(j=2;j<=4;j++)
		map[i][j-1]=map[i][j];
	map[i][4]=t;
}

void mov_r(int i)
{
	int j,t;

	t=map[i][4];
	for(j=4;j>=2;j--)
		map[i][j]=map[i][j-1];
	map[i][1]=t;
}

void mov_u(int j)
{
	int i,t;

	t=map[1][j];
	for(i=2;i<=4;i++)
		map[i-1][j]=map[i][j];
	map[4][j]=t;
}

void mov_d(int j)
{
	int i,t;

	t=map[4][j];
	for(i=4;i>=2;i--)
		map[i][j]=map[i-1][j];
	map[1][j]=t;
}

bool IDA_Star(int step)
{
	int i;

	if(step==deep)
		return check();
	if(step+get_h()>deep)   //估价函数剪枝
		return false;

	for(i=1;i<=4;i++)      //每行
	{
		mov_l(i);
		if(IDA_Star(step+1))
			return true;
		mov_r(i);           //恢复

		mov_r(i);
		if(IDA_Star(step+1))
			return true;
		mov_l(i);           //恢复
	}

	for(i=1;i<=4;i++)      //每列
	{
		mov_u(i);
		if(IDA_Star(step+1))
			return true;
		mov_d(i);           //恢复

		mov_d(i);
		if(IDA_Star(step+1))
			return true;
		mov_u(i);           //恢复
	}
	return false;
}

int main()
{
	int t,i,j;

	cin>>t;
	while(t--)
	{
		for(i=1;i<=4;i++)
			for(j=1;j<=4;j++)
				cin>>map[i][j];
		if(check())              //判断开始是否合法
		{
			cout<<"0"<<endl;
			continue;
		}
		deep=1;
		while(deep<=5)
		{
			if(IDA_Star(0))
				break;
			deep++;
		}
		if(deep<=5)
			cout<<deep<<endl;
		else
			cout<<"-1"<<endl;
	}
    return 0;
}
时间: 2024-12-19 14:29:32

HDU ACM 2234 无题I->IDA*算法的相关文章

HDU ACM 3790最短路径问题(SPFA算法实现)

分析:同时计算最短距离和花费,距离相同时还要更新费用,还要同时存储正向边和反向边. 注意:不能用cin和cout,否则会超时. #include<iostream> #include<queue> using namespace std; int u[200002]; int v[200002]; int w[200002]; int p[200002]; bool vis[1001]; int d[1001]; int cost[1001]; int first[1001]; i

转:转一个搞ACM需要的掌握的算法. .

要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来.  适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什么就眼红,  发挥自己的长处,这才是重要的. 第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,  因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打  出来.  1.最短路(Floyd.Dijstra,BellmanFord)  2.最小生成树(先写个prim,kruscal要用并查集,不好写)

hdu 1162 Eddy&#39;s picture(最小生成树算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1162 Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6866    Accepted Submission(s): 3469 Problem Description Eddy begins to like p

HDU ACM 1005 Number Sequence

Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 119732    Accepted Submission(s): 29072 Problem Description A number sequence is defined as follows:f(1) = 1, f(2) = 1, f(n) = (A

HDU ACM 1025 Constructing Roads In JGShining&amp;#39;s Kingdom-&amp;gt;二分求解LIS+O(NlogN)

#include<iostream> using namespace std; //BFS+优先队列(打印路径) #define N 500005 int c[N]; int dp[N]; //dp[i]保存的是长度为i的最长不降子序列的最小尾元素 int BS(int n,int x) //二分查找下标,当x比全部元素小时下标为1,比全部元素大时下标为n+1. { int low,high,mid; low=1,high=n; while(low<=high) { mid=(low+h

hdu 1548 A strange lift (dijkstra算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1548 题目大意:升降电梯,先给出n层楼,然后给出起始的位置,即使输出从A楼道B楼的最短时间. 注意的几点 (1)每次按一下,只能表示上或者是下,然后根据输入的看是上几层或者是下几层. (2)注意不能到底不存在的楼层. 详见代码. 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 const int IN

杭电 HDU ACM 1025 Constructing Roads In JGShining&#39;s Kingdom

Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 17732    Accepted Submission(s): 5023 Problem Description JGShining's kingdom consists of 2n(n is no mo

HDU ACM 1025 Constructing Roads In JGShining&#39;s Kingdom-&gt;二分求解LIS+O(NlogN)

#include<iostream> using namespace std; //BFS+优先队列(打印路径) #define N 500005 int c[N]; int dp[N]; //dp[i]保存的是长度为i的最长不降子序列的最小尾元素 int BS(int n,int x) //二分查找下标,当x比所有元素小时下标为1,比所有元素大时下标为n+1. { int low,high,mid; low=1,high=n; while(low<=high) { mid=(low+h

HDU ACM 1103 Flo&#39;s Restaurant

分析:借助STL的min_element实现.每次更新最先被占用的桌子,具体见注释. #include<iostream> #include<algorithm> using namespace std; int main() { int A,B,C; char s[10]; int a[102],b[102],c[102]; int curtime,count,ans; int *p; //桌子最先空闲时间 while(cin>>A>>B>>C