ssoj2437打字游戏
2015-10-06 20:15
309 查看
题意:给一个键盘,每次操作能够移动光标一次或点击一次选择,问打出给定的一串字符最少要按几次。
思路:把相同字母变为一块,预处理它向上下左右走一步能走到哪个字母块,再BFS求最短路。
思路:把相同字母变为一块,预处理它向上下左右走一步能走到哪个字母块,再BFS求最短路。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int maxn=10004; const int inf=214748364; struct data{ int v,nxt; }e[maxn]; int fst[maxn],n,m,num[55][55],cnt=0,ct=0,q[maxn],ans,dis[maxn]; char a[55][55],s[maxn],epr[maxn]; inline int get(){ char c;while(!isdigit(c=getchar())); int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48; return v; } inline void add(int x,int y){e[++ct].v=y;e[ct].nxt=fst[x],fst[x]=ct;} inline void predeal(){ for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)num[i][j]=++cnt; for(int i=1;i<=n;++i){ scanf("%s",a[i]+1); for(int j=1;j<=m;++j)epr[num[i][j]]=a[i][j]; } for(int i=1;i<=n;++i){ int j=2; while(a[i][j]==a[i][j-1])++j; int pre=j-1; for(;j<=m;++j){ if(a[i][j]!=a[i][j-1])pre=j-1; add(num[i][j],num[i][pre]); } j=m-1; while(a[i][j]==a[i][j+1])--j; for(;j>=1;--j){ if(a[i][j]!=a[i][j+1])pre=j+1; add(num[i][j],num[i][pre]); } } for(int j=1;j<=m;++j){ int i=2; while(a[i][j]==a[i-1][j])++i; int pre=i-1; for(;i<=n;++i){ if(a[i][j]!=a[i-1][j])pre=i-1; add(num[i][j],num[pre][j]); } i=n-1; while(a[i][j]==a[i+1][j])--i; for(;i>=1;--i){ if(a[i][j]!=a[i+1][j])pre=i+1; add(num[i][j],num[pre][j]); } } } inline bool cmp(const int aa,const int bb){return dis[aa]<dis[bb];} inline void bfs(char c){ int l=1,r=0; for(int i=1;i<=cnt;++i){ if(epr[i]!=c)dis[i]=inf; else q[++r]=i; } sort(q+1,q+1+r,cmp); while(l<=r){ int x=q[l];++l; for(int i=fst[x];i;i=e[i].nxt){ int y=e[i].v; if(dis[y]>dis[x]+1){ dis[y]=dis[x]+1; q[++r]=y; } } } } int main(){ n=get();m=get(); predeal(); scanf("%s",s+1); int len=strlen(s+1); s[++len]='*'; for(int i=1;i<=cnt;++i)dis[i]=inf; int l=1,r=0;q[++r]=1;dis[1]=0; while(l<=r){ int x=q[l];++l; for(int i=fst[x];i;i=e[i].nxt){ int y=e[i].v; if(dis[y]>dis[x]+1){ dis[y]=dis[x]+1; q[++r]=y; } } } for(int i=1;i<=len;++i)bfs(s[i]); ans=inf; for(int i=1;i<=cnt;++i)if(epr[i]=='*')ans=min(ans,dis[i]); printf("%d\n",ans+len); return 0; }
相关文章推荐
- swapPairs
- $在php里
- 我的Web学习之路2——密码框的提示与表单验证
- 类的扩展
- TPP并不可怕,可怕的是我们开始自我封闭
- 采用CXF框架开发HelloWorld WebService客户端
- hdu1009FatMouse's Trade
- poco c++框架库应用:数据库的连接池 推荐
- UIView与CALayer
- Visual 中控制台程序如何使用MFC类库
- python收集
- I/O多路复用
- HDU 2196 求树上所有点能到达的最远距离
- info.plist
- ios:数据持久化的几种方法浅谈
- SQL联合查询中的关键语法
- JSP include
- Arrays, Hashes, and Enumerables(homework for 01)
- JavaScript基本语法(2)
- 图标和光标