1. 程式人生 > 實用技巧 >UVA - 1343

UVA - 1343

The Rotation Game UVA - 1343

Problem:
Solution:

IDA*經典題,難點有兩個:

  • 樂觀估價函式,因為每次移動最多導致一個1/2/3進入中間的八個格子中,所以如果當前中間的1/2/3的數量加上剩餘迭代次數小與8則必然無法到達,剪枝。
  • 移動的操作方式,具體見程式碼。
Code:
/**********************************************************
* @Author: 			   Kirito
* @Last Modified by:   Kirito
* @Remark:
**********************************************************/
#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define CSE(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define Abs(x) (x>=0?x:(-x))
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define debug(x) cout<<#x<<"------"<<x<<endl
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll , ll> pll;

const int MAXN=111111;
const int mv[8][7]={
    { 0, 2, 6,11,15,20,22},
    { 1, 3, 8,12,17,21,23},
    {10, 9, 8, 7, 6, 5, 4},
    {19,18,17,16,15,14,13},
    {23,21,17,12,8,3,1},
    {22,20,15,11,6,2,0},
    {13,14,15,16,17,18,19},
    {4,5,6,7,8,9,10}
};
const int ed[8]={6,7,8,11,12,15,16,17};
int mp[25];

void mov(int x){
    for(int i=1;i<7;i++){
        swap(mp[mv[x][i]],mp[mv[x][i-1]]);
    }
    return;
}

int op;
bool over(int &mxnum){
    int num1=0,num2=0,num3=0;
    for(int i=0;i<8;i++){
        if(mp[ed[i]]==1) num1++;
        if(mp[ed[i]]==2) num2++;
        if(mp[ed[i]]==3) num3++;
    }
    mxnum=max(max(num1,num2),num3);
    if(num1==8) {op=1;return true;}
    if(num2==8) {op=2;return true;}
    if(num3==8) {op=3;return true;}
    return false;
}

char path[MAXN];
bool ok;
void dfs(int p,int q){
    if(ok) return;
    int mxnum=0;
    if(over(mxnum)) {ok=true;return;}
    if(mxnum+q-p<8) return;
    int mp1[25];
    memcpy(mp1,mp,sizeof(mp));
    for(int i=0;i<8;i++){
        if(ok) return;
        mov(i);
        path[p]='A'+i;
        dfs(p+1,q);
        memcpy(mp,mp1,sizeof(mp1));
    }
    return;
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
    FAST;
    while(cin>>mp[0]&&mp[0]){
        for(int i=1;i<24;i++){
            cin>>mp[i];
        }
        ok=false;CSE(path,'\0');
        int sp=0;
        for(;;sp++){
            dfs(0,sp);
            if(ok){
                break;
            }
        }
        //debug(sp);
        if(!sp) cout<<"No moves needed"<<endl;
        else{
            for(int i=0;i<sp;i++) cout<<path[i];
            cout<<endl;
        }
        cout<<op<<endl;
    }
	return 0;
}