您的位置:首页 > 其它

例题7-12 UVA - 1343 The Rotation Game 旋转游戏(IDA*)

2016-05-04 00:22 465 查看
题目大意:

给一个棋盘,问最少进行几次旋转使得中间的数字全部相等!(并且字典序最小!)

思路:

借鉴了代码仓库,感觉写的很巧妙,简单记录一下!

大致思路:

用line [][] 二维数组给棋盘进行标号!

a[] 一维数组代表当前的棋盘中棋子的标号!

center[] 一维数组代表棋盘中间棋子的标号!

rev[]数组进行反转列 ,减少了很多代码!

先判断是否合法,合法的话直接输出。NO need。。。 还有数字!

否则进行迭代加深

迭代加深中要说的有两点:

1.move函数 move(i)是进行移动!

move(rev[i])是倒回来!很巧妙!

2.if (cur + geth() > maxd)return false; 这个意思代表 需要改的 + 已经改的大于maxd的话 直接return false;进行下一次迭代加深!

注意:

当一上来就合法时别忘了输出数字,,WA了不知道几遍了~~~

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 30;
int line[maxn][maxn] = {
{0, 2, 6, 11, 15, 20, 22}, // A; 0
{1, 3, 8, 12, 17, 21, 23}, // B; 1
{10, 9, 8, 7, 6, 5, 4}, // C; 2
{19, 18, 17, 16, 15, 14, 13}, // D; 3
};
const int rev[maxn] = {5, 4, 7, 6, 1, 0, 3, 2};
const int center[maxn] = {6, 7, 8, 11, 12, 15, 16, 17};
int a[maxn];
char s[10000];
int dif(int k){
int sum = 0;
for (int i = 0; i < 8; ++i)
if (a[center[i]] != k)++sum;
return sum;
}
int geth(){
return min(min(dif(1),dif(2)),dif(3));
}
void move(int k){
int temp = a[line[k][0]];
for (int i = 0; i <= 5; ++i)
a[line[k][i]] = a[line[k][i+1]];
a[line[k][6]] = temp;
}
bool is_ok(){
for (int i = 1; i < 8; ++i)
if (a[center[i]] != a[center[0]])return false;
return true;
}
bool dfs(int cur,int maxd){
if (is_ok()){
s[cur] = 0;
printf("%s\n",s);
return true;
}
if (cur + geth() > maxd)return false;//需要改的+已经改了的 大于maxd  return false;
for (int i = 0; i < 8; ++i){
s[cur] = 'A' + i;
move(i);
if (dfs(cur+1,maxd))return true;
move(rev[i]);
}
return false;
}
int main(){
for (int i = 4; i < 8; ++i)
for (int j = 0; j < 7; ++j)
line[i][j] = line[rev[i]][6-j];
while(scanf("%d",&a[0]) == 1 && a[0]){
for (int i = 1; i < 24; ++i)scanf("%d",&a[i]);
if (is_ok()){printf("No moves needed\n%d\n",a[16]);continue;}
for (int maxd = 0;; ++maxd){
if (dfs(0,maxd))break;
}
printf("%d\n",a[16]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: