http://acm.timus.ru/problem.aspx?space=1&num=1806
只要算法对 ural 一般不会卡时间的
这个题是一个简单的最短路 spfa
关键在于找边 找边的方法是 对于每一个点 枚举它的所有可能的变化 搜索是否有和变化后的字符串一样的
搜索的时候既可以用 map 也可以 自己写字典树
map 写起来简单 不过 字典树效率要高
注意边的个数 要在 N*50
代码1:
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<set> #include<map> #include<string> #include<queue> #include<stack> #include <iomanip> using namespace std; #define LL long long const int INF=0x3f3f3f3f; const int N=50005; int head[N],I; struct node { int j,next,t; }side[N*50]; int cost[N]; int f[N]; bool in[N]; int dist[N]; char s[N][12]; stack<int>st; struct node1 { int k; struct node1 *next[10]; }; struct node1 *root; void add(int i,int j,int t) {//cout<<i<<" "<<j<<" "<<t<<endl; side[I].j=j; side[I].t=t; side[I].next=head[i]; head[i]=I++; } int costtime(int i,int j) { for(int x=0;x<10;++x) { if(s[i][x]!=s[j][x]) return cost[x]; } return 0; } bool spfa(int st,int nd) { memset(in,false,sizeof(in)); memset(dist,-1,sizeof(dist)); queue<int>qt; qt.push(st); in[st]=true; dist[st]=0; while(!qt.empty()) { int x=qt.front();qt.pop(); in[x]=false; for(int t=head[x];t!=-1;t=side[t].next) { int j=side[t].j; if(dist[j]==-1||dist[j]>dist[x]+side[t].t) { dist[j]=dist[x]+side[t].t; f[j]=x; if(!in[j]) { in[j]=true; qt.push(j); } } } } if(dist[nd]==-1) return false; return true; } void insert(int x) {//cout<<x<<endl; struct node1 *w,*t=root; for(int i=0;i<10;++i) { if(t->next[s[x][i]-'0']==NULL) { w=new node1; for(int j=0;j<10;++j) w->next[j]=NULL; t->next[s[x][i]-'0']=w; } t=t->next[s[x][i]-'0']; } t->k=x; } int Fnum(int x) { struct node1 *t=root; for(int i=0;i<10;++i) { if(t->next[s[x][i]-'0']==NULL) return 0; t=t->next[s[x][i]-'0']; } return t->k; } int main() { //freopen("data.in","r",stdin); int n; while(scanf("%d",&n)!=EOF) { root=new node1; for(int i=0;i<10;++i) root->next[i]=NULL; for(int i=0;i<10;++i) scanf("%d",&cost[i]); getchar(); for(int i=1;i<=n;++i) { gets(s[i]); insert(i); } memset(head,-1,sizeof(head)); I=0; int k; for(int i=1;i<=n;++i) { for(int l=0;l<10;++l) { char ctmp=s[i][l]; for(char c='0';c<='9';++c) { if(ctmp==c) continue; s[i][l]=c; if((k=Fnum(i))) { s[i][l]=ctmp; add(i,k,costtime(i,k)); continue; } } s[i][l]=ctmp; } for(int l=0;l<10;++l) for(int r=l+1;r<10;++r) { if(s[i][l]==s[i][r]) continue; swap(s[i][l],s[i][r]); if((k=Fnum(i))) { swap(s[i][l],s[i][r]); add(i,k,costtime(i,k)); continue; } swap(s[i][l],s[i][r]); } } if(!spfa(1,n)) printf("-1\n"); else { while(!st.empty()) st.pop(); int k=n; while(k!=1) { st.push(k); k=f[k]; } printf("%d\n",dist[n]); printf("%d\n",st.size()+1); printf("1"); while(!st.empty()) { printf(" %d",st.top()); st.pop(); } printf("\n"); } } return 0; }
代码2:
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<set> #include<map> #include<string> #include<queue> #include<stack> #include <iomanip> using namespace std; #define LL long long const int INF=0x3f3f3f3f; const int N=50005; int head[N],I; struct node { int j,next,t; }side[N*50]; int cost[N]; map<string,int>mt; map<string,int>::iterator it; int f[N]; bool in[N]; int dist[N]; string s[N]; stack<int>st; void add(int i,int j,int t) {//cout<<i<<" "<<j<<" "<<t<<endl; side[I].j=j; side[I].t=t; side[I].next=head[i]; head[i]=I++; } int costtime(int i,int j) { for(int x=0;x<10;++x) { if(s[i][x]!=s[j][x]) return cost[x]; } return 10; } bool spfa(int st,int nd) { memset(in,false,sizeof(in)); memset(dist,-1,sizeof(dist)); queue<int>qt; qt.push(st); in[st]=true; dist[st]=0; while(!qt.empty()) { int x=qt.front();qt.pop(); in[x]=false; for(int t=head[x];t!=-1;t=side[t].next) { int j=side[t].j; if(dist[j]==-1||dist[j]>dist[x]+side[t].t) { dist[j]=dist[x]+side[t].t; f[j]=x; if(!in[j]) { in[j]=true; qt.push(j); } } } } if(dist[nd]==-1) return false; return true; } int main() { //freopen("data.in","r",stdin); int n; while(cin>>n) { for(int i=0;i<10;++i) cin>>cost[i]; mt.clear(); for(int i=1;i<=n;++i) { cin>>s[i]; mt[s[i]]=i; } memset(head,-1,sizeof(head)); I=0; for(int i=1;i<=n;++i) { s[0]=s[i]; for(int l=0;l<10;++l) { char ctmp=s[i][l]; for(char c='0';c<='9';++c) { if(ctmp==c) continue; s[i][l]=c; if((it=mt.find(s[i]))!=mt.end()) add(i,it->second,costtime(0,it->second)); } s[i][l]=ctmp; } for(int l=0;l<10;++l) for(int r=l+1;r<10;++r) { if(s[i][l]==s[i][r]) continue; swap(s[i][l],s[i][r]); if((it=mt.find(s[i]))!=mt.end()) add(i,it->second,costtime(0,it->second)); swap(s[i][l],s[i][r]); } } if(!spfa(1,n)) cout<<"-1"<<endl; else { while(!st.empty()) st.pop(); int k=n; while(k!=1) { st.push(k); k=f[k]; } cout<<dist[n]<<endl; cout<<(st.size()+1)<<endl; cout<<"1"; while(!st.empty()) { cout<<" "<<st.top(); st.pop(); } cout<<endl; } } return 0; }