您的位置:首页 > 其它

poj_2286 IDA*

2015-09-03 14:20 344 查看

题目大意

给定一个由数字组成的#字型网格,和一定的移动规则,问最少需要多少次移动才能达到要求的结果。

题目分析

要求最少需要几步到达结果,可以考虑广度优先搜索算法,或者迭代加深深度优先搜索(IDA*),这里使用IDA*算法。
在剪枝的时候:
1. 考虑估价函数H(),表示当前中间八个格子中最少需要移动多少次才能相同(即8 -
相同数字最多的个数);
2. 前后两次移动不同为逆操作(即同一列,但不同方向)
3. 不能连续7次进行移动同一列,且同一方向
详细见 CanCut 函数。

实现(c++)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define MAX(a, b) a>b? a :b
#define MAX_STEP 1000
int gOrderMoved[MAX_STEP];
int gIrreleventQueuee[4] = { 1, 0, 3, 2 };

int gCell[25];
int gCellIndexInQueue[4][7];
int gMoveOrder[4][2] = { { 0, 5 }, { 1, 4 }, { 7, 2 }, { 6, 3 } };
int gMoveQueue[8] = {0, 1, 2, 3, 1, 0, 3, 2};
int gMoveDir[8] = {0, 0, 1, 1, 1, 1, 0, 0};
int gCenterCellIndex[8] = { 6, 7, 8, 11, 12, 15, 16, 17 };
int gMinStep;
void Init(){
gCellIndexInQueue[0][0] = 0;
gCellIndexInQueue[0][1] = 2;
gCellIndexInQueue[0][2] = 6;
gCellIndexInQueue[0][3] = 11;
gCellIndexInQueue[0][4] = 15;
gCellIndexInQueue[0][5] = 20;
gCellIndexInQueue[0][6] = 22;

gCellIndexInQueue[1][0] = 1;
gCellIndexInQueue[1][1] = 3;
gCellIndexInQueue[1][2] = 8;
gCellIndexInQueue[1][3] = 12;
gCellIndexInQueue[1][4] = 17;
gCellIndexInQueue[1][5] = 21;
gCellIndexInQueue[1][6] = 23;

for (int i = 0; i < 7; i++){
gCellIndexInQueue[2][i] = 4 + i;
}

for (int i = 0; i < 7; i++){
gCellIndexInQueue[3][i] = 13 + i;
}
}

bool IsCenterSame(){
int num = gCell[6];
for (int i = 0; i < 8; i++){
if (gCell[gCenterCellIndex[i]] != num){
return false;
}
}
return true;
}

void Rotate(int order){
int move_queue = gMoveQueue[order];
int move_dir = gMoveDir[order];
int tmp;
if (move_dir == 0){
tmp = gCell[gCellIndexInQueue[move_queue][0]];
for (int i = 0; i < 6; i++)
gCell[gCellIndexInQueue[move_queue][i]] = gCell[gCellIndexInQueue[move_queue][i + 1]];
gCell[gCellIndexInQueue[move_queue][6]] = tmp;
}
else{
tmp = gCell[gCellIndexInQueue[move_queue][6]];
for (int i = 6; i > 0; i--)
gCell[gCellIndexInQueue[move_queue][i]] = gCell[gCellIndexInQueue[move_queue][i - 1]];
gCell[gCellIndexInQueue[move_queue][0]] = tmp;
}
}

int GetH(){
int count[4] = { 0, 0, 0, 0 };
for (int i = 0; i < 8; i++){
count[gCell[gCenterCellIndex[i]]] ++;
}
int max = MAX(count[1], count[2]);
max = MAX(max, count[3]);
return 8 - max;
}

bool CanCut(int moved_step, int next_order){
if (moved_step == 0){
return false;
}
int k = moved_step - 1;
int next_queue = gMoveQueue[next_order];
int next_dir = gMoveDir[next_order];

int irrelevent_queue = gIrreleventQueuee[next_queue];
int same_order_count = 0;
while (k >= 0){

if (same_order_count >= 6)
return true;

while (k >= 0 && gMoveQueue[gOrderMoved[k]] == irrelevent_queue){
k--;
}
if (k < 0){
return false;
}
int queue = gMoveQueue[gOrderMoved[k]];
int dir = gMoveDir[gOrderMoved[k]];
if (queue == next_queue){
if (dir != next_dir){
return true;
}
else{
same_order_count++;
}
}
else{
return false;
}

k--;
}

return false;
}
void MoveToCenterSame(int moved_step,  bool *moved_same){
if (*moved_same){
return;
}
if (IsCenterSame()){
for (int i = 0; i < gMinStep; i++){
printf("%c", 'A' + gOrderMoved[i]);
}
if (gMinStep == 0){
printf("No moves needed");
}
printf("\n");
printf("%d\n", gCell[6]);
*moved_same = true;
return;
}
if (moved_step + GetH() > gMinStep){
return;
}
for (int next_order = 0; next_order < 8; next_order++){
if (CanCut(moved_step, next_order)){
continue;
}
if (*moved_same){
return;
}
gOrderMoved[moved_step] = next_order;
Rotate(next_order);
MoveToCenterSame(moved_step + 1, moved_same);
int reback_order = gMoveOrder[gMoveQueue[next_order]][! gMoveDir[next_order]];
Rotate(reback_order);
}

}

void Solve(){
gMinStep = 0;
while (true){
bool moved_same = false;
MoveToCenterSame(0, &moved_same);
if (moved_same){
break;
}
gMinStep++;
}
}

int main(){
Init();
while (true){
scanf("%d", gCell);
if (gCell[0] == 0){
break;
}
for (int i = 1; i < 24; i++){
scanf("%d", gCell + i);
}
Solve();

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: