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,' ');
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;
}