已知一个密码锁,最多有6位数字,每个数字都是10进制数。有100个按钮,每个按钮可以让某些数字转动若干次。你只能通过按按钮来转动密码锁。问最小的按按钮的次数,输出字典序最小的序列。
搜索,BFS即可。把每个状态当成一个点,复杂度略微有点高..最坏有10^8条边...但是好像不会到这么坏...
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=~0u>>1;
int minv[1000000];
int from[1000000];
int que[1000000];
int ans[1000000];
int a[100];
int pow[7];
int d,n,s,t,p,q,m;
inline int calTo(int i,int j) {
int ans=0,k;
for (k=0;k<d;k++) {
ans+=(i+j)%10*pow[k];
i/=10;
j/=10;
}
return ans;
}
inline int cal(int i,int j) {
int ans=0,k;
for (k=0;k<d;k++) {
ans+=(j-i+2000000)%10*pow[k];
i/=10;
j/=10;
}
return ans;
}
inline void print(int x) {
for (int k=d-1;k>=0;k--) {
printf("%d",x/pow[k]%10);
}
printf("\n");
}
int main() {
int i,j,k;
pow[0]=1;
for (i=0;i<6;i++) pow[i+1]=pow[i]*10;
while (scanf("%d%d",&d,&n)!=EOF) {
for (i=0;i<n;i++) scanf("%d",&a[i]);
sort(a,a+n);
m=pow[d];
scanf("%d%d",&s,&t);
for (i=0;i<m;i++) minv[i]=INF;
p=q=0;
que[q++]=s;
minv[s]=0;
while (p!=q&&que[p]!=t) {
i=que[p++];
//printf("from %d\n",i);
for (j=0;j<n;j++) {
k=calTo(i,a[j]);
//printf(" add %d = %d\n",a[j],k);
if (minv[k]==INF) {
minv[k]=minv[i]+1;
from[k]=i;
que[q++]=k;
}
}
}
if (minv[t]==INF) printf("-1\n");
else {
p=0;q=t;
while (q!=s) {
//printf("-- %d + %d -> %d\n",from[q],cal(from[q],q),q);
ans[p++]=cal(from[q],q);
q=from[q];
}
printf("%d\n",p);
while (p--) {
print(ans[p]);
}
}
}
return 0;
}