[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 }

 

转载于:https://www.cnblogs.com/skylee03/p/7591860.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值