2 条题解
-
0
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int op[8][7]={ //8个操作的格子编号 {0,2,6,11,15,20,22}, //A {1,3,8,12,17,21,23}, //B {10,9,8,7,6,5,4}, //C {19,18,17,16,15,14,13},//D {23,21,17,12,8,3,1}, //E {22,20,15,11,6,2,0}, //F {13,14,15,16,17,18,19},//G {4,5,6,7,8,9,10} //H }; int cent[8]={6,7,8,11,12,15,16,17}; //中心 int iop[8]={5,4,7,6,1,0,3,2}; //逆操作 int dep,a[24],path[100]; void operate(int x){ //第x种操作 int t=a[op[x][0]]; for(int i=0; i<6; i++) a[op[x][i]]=a[op[x][i+1]]; a[op[x][6]]=t; } bool check(){ //中心数字是否相同 for(int i=1; i<8; i++) if(a[cent[i]]!=a[cent[0]]) return False; return True; } int f(){ //估价函数: f=8-k static int cnt[4]; memset(cnt,0,sizeof cnt); for(int i=0; i<8; i++) cnt[a[cent[i]]]++; int k=0; //中心数字最多的出现次数为k for(int i=1; i<=3; i++) k=max(k,cnt[i]); return 8-k; //换掉不同数字,至少操作8-k次 } //第u层, 上一次操作为last bool dfs(int u,int last){ if(u+f()>dep) return False; if(check()) return True; for(int i=0; i<8; i++){ if(iop[i]==last) continue; operate(i); //操作一次 path[ u ]=i; if(dfs(u+1,i)) return True; operate(iop[i]); //恢复现场 } return False; } int main(){ while(scanf("%d",&a[0]),a[0]){ for(int i=1;i<24;i++)scanf("%d",&a[i]); for(dep=0; !dfs(0,-1); dep++); if(!dep) printf("No moves needed"); for(int i=0; i<dep; i++) printf("%c",'A'+path[i]); printf("\n%d\n",a[6]); } }zjj代码:
#include<cstdio> #include<cstring> using namespace std; inline int mymax(int x,int y){return x>y?x:y;} inline int mymin(int x,int y){return x<y?x:y;} int a[30]; inline bool pd(){return (a[7]==a[8] && a[8]==a[9] && a[9]==a[12] && a[12]==a[13] && a[13]==a[16] && a[16]==a[17] && a[17]==a[18]);} int fuck[]={0,7,8,9,12,...,17,18}; inline int check() { int cnt=100; //左右第一个 for(int t=1;t<=3;t++) { int tot=0; for(int i=1;i<=8;i++)tot+=(a[fuck[i]]!=t); cnt=mymin(cnt,tot); } return cnt; } inline void heng(int l,int r,int type) { if(!type)//左拉 { int x=a[l]; for(int i=l;i<r;i++)a[i]=a[i+1]; a[r]=x; } else//右拉 { int x=a[r]; for(int i=r;i>l;i--)a[i]=a[i-1]; a[l]=x; } } int li[2][8]={{0,1,3,7,12,16,21,23},{0,2,4,9,13,18,22,24}}; inline void lie(int *list,int type) { if(!type)//上拉 { int x=a[list[1]]; for(int i=1;i<7;i++)a[list[i]]=a[list[i+1]]; a[list[7]]=x; } else//下拉 { int x=a[list[7]]; for(int i=7;i>=2;i--)a[list[i]]=a[list[i-1]]; a[list[1]]=x; } -
0
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int op[8][7]={ //8个操作的格子编号 {0,2,6,11,15,20,22}, //A {1,3,8,12,17,21,23}, //B {10,9,8,7,6,5,4}, //C {19,18,17,16,15,14,13},//D {23,21,17,12,8,3,1}, //E {22,20,15,11,6,2,0}, //F {13,14,15,16,17,18,19},//G {4,5,6,7,8,9,10} //H }; int cent[8]={6,7,8,11,12,15,16,17}; //中心 int iop[8]={5,4,7,6,1,0,3,2}; //逆操作 int dep,a[24],path[100]; void operate(int x){ //第x种操作 int t=a[op[x][0]]; for(int i=0; i<6; i++) a[op[x][i]]=a[op[x][i+1]]; a[op[x][6]]=t; } bool check(){ //中心数字是否相同 for(int i=1; i<8; i++) if(a[cent[i]]!=a[cent[0]]) return False; return True; } int f(){ //估价函数: f=8-k static int cnt[4]; memset(cnt,0,sizeof cnt); for(int i=0; i<8; i++) cnt[a[cent[i]]]++; int k=0; //中心数字最多的出现次数为k for(int i=1; i<=3; i++) k=max(k,cnt[i]); return 8-k; //换掉不同数字,至少操作8-k次 } //第u层, 上一次操作为last bool dfs(int u,int last){ if(u+f()>dep) return False; if(check()) return True; for(int i=0; i<8; i++){ if(iop[i]==last) continue; operate(i); //操作一次 path[ u ]=i; if(dfs(u+1,i)) return True; operate(iop[i]); //恢复现场 } return False; } int main(){ while(scanf("%d",&a[0]),a[0]){ for(int i=1;i<24;i++)scanf("%d",&a[i]); for(dep=0; !dfs(0,-1); dep++); if(!dep) printf("No moves needed"); for(int i=0; i<dep; i++) printf("%c",'A'+path[i]); printf("\n%d\n",a[6]); } }
zjj代码:#include<cstdio> #include<cstring> using namespace std; inline int mymax(int x,int y){return x>y?x:y;} inline int mymin(int x,int y){return x<y?x:y;} int a[30]; inline bool pd(){return (a[7]==a[8] && a[8]==a[9] && a[9]==a[12] && a[12]==a[13] && a[13]==a[16] && a[16]==a[17] && a[17]==a[18]);} int fuck[]={0,7,8,9,12,13,16,17,18}; inline int check() { int cnt=100; //左右第一个 for(int t=1;t<=3;t++) { int tot=0; for(int i=1;i<=8;i++)tot+=(a[fuck[i]]!=t); cnt=mymin(cnt,tot); } return cnt; } inline void heng(int l,int r,int type) { if(!type)//左拉 { int x=a[l]; for(int i=l;i<r;i++)a[i]=a[i+1]; a[r]=x; } else//右拉 { int x=a[r]; for(int i=r;i>l;i--)a[i]=a[i-1]; a[l]=x; } } int li[2][8]={{0,1,3,7,12,16,21,23},{0,2,4,9,13,18,22,24}}; inline void lie(int *list,int type) { if(!type)//上拉 { int x=a[list[1]]; for(int i=1;i<7;i++)a[list[i]]=a[list[i+1]]; a[list[7]]=x; } else//下拉 { int x=a[list[7]]; for(int i=7;i>=2;i--)a[list[i]]=a[list[i-1]]; a[list[1]]=x; } } int limit;char ans[30];int top; int fan[]={5,4,7,6,1,0,3,2}; int be1[]={0,0,1,1,0,0,1,1}; int be2[]={0,1,0,1,2,3,2,3}; inline void do_op(int x) { if(!x)lie(li[0],0); else if(x==1)lie(li[1],0); else if(x==2)heng(5,11,1); else if(x==3)heng(14,20,1); else if(x==4)lie(li[1],1); else if(x==5)lie(li[0],1); else if(x==6)heng(14,20,0); else if(x==7)heng(5,11,0); } bool dfs(int dep,int pre/*被ban掉的操作*/) { int shit=check(); if(dep+shit>limit)return 0; if(!shit)return 1; for(int t=0;t<=7;t++) { if(pre!=100 && (t==fan[pre] || (be1[t]==be1[pre] && be2[t]<be2[pre])))continue; do_op(t); if(dfs(dep+1,t)==1) { ans[dep]='A'+t; return 1; } do_op(fan[t]); } return 0; } int main() { while(1) { scanf("%d",&a[1]); if(!a[1])break; for(int i=2;i<=24;i++)scanf("%d",&a[i]); if(pd()==1) { printf("No moves needed\n%d\n",a[7]); continue; } for(int i=1;i<=100;i++) { limit=i; if(dfs(0,100)==1) { ans[i]='\0'; break; } } printf("%s\n",ans); printf("%d\n",a[7]); } return 0; }
- 1
信息
- ID
- 2980
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 11
- 已通过
- 2
- 上传者