[SimpleOJ229]隧道
题目大意:
有10个格子,初始状态a和b分别在5和6上。
现在有n个任务,每个任务都有特定的位置。
在每个单位时间,a和b可以分别进行以下事件中的任意一件:
1.向左(右)移动一个格子;
2.锁定在当前格子执行任务。
(a和b不能同时执行任务,且同一时刻a必须严格在b左边)。
问完成所有任务的最小时间。
思路:
动态规划。
f[i][j][k]表示完成第i个任务后,a在j且b在k时所经过的最少时间。
设当前任务为p,当前待转移的状态为f[i][p]或f[p][i],枚举完成上一个任务后a和b所在的位置j和l,并加上分别从j,l移动到p,i或i,p的最大时间。
数据格式有点问题,要手动判断换行符和空行。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 #include<algorithm> 5 const int inf=0x40000000; 6 const int N=101,M=11; 7 char s[N]; 8 int f[N][M][M]; 9 bool get(char s[]) { 10 char ch; 11 int n=0; 12 while(!isdigit(ch=getchar())) { 13 if(!~ch) return false; 14 if(ch=='\n') { 15 s[n]='\0'; 16 return true; 17 } 18 } 19 s[n++]=ch; 20 while(isdigit(ch=getchar())) { 21 s[n++]=ch; 22 } 23 s[n]='\0'; 24 while(ch!='\n') ch=getchar(); 25 return true; 26 } 27 int main() { 28 while(get(s)) { 29 int n=strlen(s); 30 if(!n) { 31 puts("0"); 32 continue; 33 } 34 std::fill(&f[0][0][0],&f[n][M-1][M],inf); 35 f[0][5][6]=0; 36 for(register int k=1;k<=n;k++) { 37 int p=s[k-1]-'0'; 38 if(!p) p=10; 39 for(register int i=1;i<p;i++) { 40 for(register int j=1;j<M;j++) { 41 for(register int l=j+1;l<M;l++) { 42 f[k][i][p]=std::min(f[k][i][p],f[k-1][j][l]+std::max(std::abs(i-j),std::abs(p-l)+1)); 43 } 44 } 45 } 46 for(register int i=p+1;i<M;i++) { 47 for(register int j=1;j<M;j++) { 48 for(register int l=j+1;l<M;l++) { 49 f[k][p][i]=std::min(f[k][p][i],f[k-1][j][l]+std::max(std::abs(p-j)+1,std::abs(i-l))); 50 } 51 } 52 } 53 } 54 int ans=inf; 55 for(register int i=1;i<M;i++) { 56 for(register int j=1;j<M;j++) { 57 ans=std::min(ans,f[n][i][j]); 58 } 59 } 60 printf("%d\n",ans); 61 } 62 return 0; 63 }