• poj_2286 IDA*


    题目大意

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

    题目分析

        要求最少需要几步到达结果,可以考虑广度优先搜索算法,或者迭代加深深度优先搜索(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("
    ");
    		printf("%d
    ", 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;
    }
    
  • 相关阅读:
    IT经典书籍——Head First系列【推荐】
    IT经典书籍——Head First系列【推荐】
    使用JSP实现用户登录
    使用JSP实现用户登录
    【知乎精选】如何面试一个产品经理?如何判断一个产品经理是否是一个很牛的产品经理?
    淘宝API总结
    「用户标签」在数据库设计时应该如何存储?
    【爬虫集合】抖音API分析
    商业架构体系
    短视频带货
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4780157.html
Copyright © 2020-2023  润新知