Digit Dancing
題意:
給你8個數,他們的絕對值組成一個1~8的一個排列,每次操作允許找到同時滿足下列情況的兩個數
ai,aj 兩個數一正一負abs(ai)+abs(aj) 是素數
問最少操作幾次讓這8個數按絕對值遞增排列。
題解:
8!很小,按題意爆搜即可。
#include<bits/stdc++.h>
using namespace std;
struct node{
int a[10], t;
node(){ t = 0; for(int i = 1; i < 10; ++i) a[i] = 0; }
void scan(){ for(int i = 1; i <= 8; ++i) scanf("%d", a+i); t = 0; }
int hash(){
int res = 0;
for(int i = 1; i <= 8; ++i) res = res*10+abs(a[i]);
return res;
}
node movel(int i, int pos){
node res = *this;
if(i < pos){
while(res.a[i+1] != a[pos]) swap(res.a[i+1], res.a[i]), ++i;
}
else{
while(res.a[i+1] != a[pos]) swap(res.a[i-1], res.a[i]), --i;
}
return res;
}
node mover(int i, int pos){
node res = *this;
if(i < pos){
while(res.a[i-1] != a[pos]) swap(res.a[i+1], res.a[i]), ++i;
}
else{
while(res.a[i-1] != a[pos]) swap(res.a[i-1], res.a[i]), --i;
}
return res;
}
bool solved(){
for(int i = 1; i <= 8; ++i){
if(a[i] != i && a[i] != -i) return 0;
}
return 1;
}
}s;
int prime[50] = {0};
void init(){
prime[2] = prime[3] = 1;
for(int i = 5; i < 50; i += 2){
for(int j = 2; j < i; ++j){
if(i%j == 0) break;
if(j == i-1) prime[i] = 1;
}
}
}
int bfs(node s){
queue<node>q;
set<int>st;
q.push(s); st.insert(s.hash());
while(!q.empty()){
node now = q.front(); q.pop();
if(now.solved()) return now.t;
now.t++;
for(int i = 1; i <= 8; ++i){
if(now.a[i] > 0) continue; // <0
for(int j = 1; j <= 8; ++j){
if(now.a[j] < 0) continue; // >0
if(!prime[-now.a[i]+now.a[j]]) continue;
node nex = now.movel(i, j);
if(st.count(nex.hash()) == 0){
q.push(nex);
st.insert(nex.hash());
}
nex = now.mover(i, j);
if(st.count(nex.hash()) == 0){
q.push(nex);
st.insert(nex.hash());
}
nex = now.movel(j, i);
if(st.count(nex.hash()) == 0){
q.push(nex);
st.insert(nex.hash());
}
nex = now.mover(j, i);
if(st.count(nex.hash()) == 0){
q.push(nex);
st.insert(nex.hash());
}
}
}
}
return -1;
}
int main(){
init();
int T, ca = 1;
scanf("%d", &T);
while(T--){
s.scan();
printf("Case %d: %d\n", ca++, bfs(s));
}
}