• [51nod1373]哈利与他的机械键盘


      作为一名屌丝程序员,机械键盘是哈利梦寐以求的神器。终于,在除夕夜的时候,他爸爸送了他一个机械键盘。
      哈利的键盘与我们平常所见到的的键盘不一样,我们可以认为他的键盘是一个500*500的矩形,其中26个字母键分布在某些格点上。这天,心血来潮的哈利想用他心爱的键盘写一些代码,假设他的代码只有一行,而且都是由小写的英文字母构成。由于键盘上的按键分布在不同的地方,哈利码代码时,移动手指要花费一些能量,其花费能量为上一次敲击的键,与当前要敲的键的曼哈顿距离。为了节省力气,哈利可以不必完全按照要敲的代码输入,他可以跳着输,比如helloworld,他可以按照d r o o l l l e h w的顺序输入,但是为了让输入的代码是他想要的输入顺序,在输入的过程中,他可能需要移动光标,在相应的位置输入对应的单词,作为一名熟练的vim选手,哈利将光标移动一个位置仅需1的费用,比如他想输入qpy,他按q->y->p的顺序输入,那么花费的总的能量为cost(q,y)+1+cost(y,p),其中cost(x,y)为字母x,y之间的曼哈顿距离,当中花费的1的能量为输入y后,往左移动一次光标所花费的能量。当然,人的记忆力都是有限的,哈利最多只能记住连续10个位置的字母有没有输入过,也就是说如果想输入第i个字符,要么i<=10或者所有第i-10(包含)以前的字符都已经输入,比如第1个位置的字母还没有输,他就不能考虑第11个字母,因为一旦考虑第11个字母的时候,他就忘了第1个字母有没有输了。现在哈利想知道,他敲完这篇代码,最少需要多少能量?哈利第一次输入的时候可以不花费能量。

     Input
      前26行,每行两个整数x, y (0<=x<500, 0<=y<500)以空格分开,表示26个英文字母键a-z所在位置,保证不会有两个键在相同的位置
      第27行为一个长度不超过100的字符串(非空),表示哈利要敲的代码,由小写字母a-z组成
     Output
      输出一个整数,表示哈利敲完代码最少花多少能量

      状压DP。f[i][j][zt]表示考虑了前i位(i-10以前的都填完了),在最后10位里的第j位,最后10位里是否填了数的状态为zt。

      转移的话,一种是从j挪到最后10位里的另外一个未填的位,另一种是从j挪到第i+x位,要求x<=10且i-10..i-10+x都填了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #define ll long long
     7 #define ui unsigned int
     8 #define ull unsigned long long
     9 const int maxn=100233,inf=1002333333;
    10 int f[102][10][1233];
    11 int dis[1233][10][11],map[29][29],x[29],y[29];
    12 int i,j,k,n,m;
    13 char s[123],s1[123];
    14 
    15 int ra,fh;char rx;
    16 inline int read(){
    17     rx=getchar(),ra=0,fh=1;
    18     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
    19     if(rx=='-')fh=-1,rx=getchar();
    20     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
    21 }
    22 
    23 inline void mins(int &a,int b){if(b<a)a=b;}
    24 inline int run(int n){
    25     int i,j,_j,zt;register int j1,_j1,zt1;int mx=1<<10,nowf;
    26 //        for(i=1;i<=n;i++)printf("%c",s[i]+'a'-1);puts("");
    27     for(i=10;i<=n;i++)memset(f[i],60,sizeof(f[i]));
    28     for(i=0;i<10;i++)f[10][i][1<<i]=0;
    29     
    30     for(i=10;i<=n;i++)for(zt=1;zt<mx;zt++)for(j=0,_j=i-9+j;j<10;j++,_j++)if(zt&(1<<j)){
    31         nowf=f[i][j][zt];
    32         for(j1=0,_j1=i-9+j1;j1<10;j1++,_j1++)if(!(zt&(1<<j1)))
    33             mins(f[i][j1][zt|(1<<j1)],nowf+map[s[_j]][s[_j1]]+dis[zt][j][j1]);
    34         for(j1=0,_j1=i+1+j1,zt1=zt>>1;j1<10&&(zt&(1<<j1))&&_j1<=n;j1++,_j1++,zt1>>=1)
    35             mins(f[_j1][9][zt1|(1<<9)],nowf+map[s[_j]][s[_j1]]+dis[zt][j][10]);
    36     }
    37     int ans=1<<30;
    38     for(i=0;i<10;i++)mins(ans,f[n][i][mx-1]);
    39 //        printf("   %d
    ",ans);
    40     return ans;
    41 }
    42 inline int abs(int x){return x<0?-x:x;}
    43 int main(){
    44     int mx=1<<10;
    45     for(i=0;i<mx;i++)for(j=0;j<10;j++)if(i&(1<<j))for(k=0;k<11;k++)if(!(i&(1<<k))){
    46         int a=j,b=k;if(a>b)std::swap(a,b);
    47         for(int i1=a+1;i1<b;i1++)if(i&(1<<i1))dis[i][j][k]++;
    48         dis[i][j][k]+=k<j;
    49     }
    50     
    51     for(i=1;i<=26;i++){
    52         x[i]=read(),y[i]=read();
    53         for(j=1;j<=i;j++)map[i][j]=map[j][i]=abs(x[i]-x[j])+abs(y[i]-y[j]);
    54     }
    55     scanf("%s",s+1),n=strlen(s+1);
    56     for(i=1;i<=n;i++)s[i]-='a'-1;
    57     
    58     if(n>=10)return printf("%d
    ",run(n)),0;
    59     for(i=1;i<=n;i++)s1[i+10-n]=s[i];
    60     int ans=1<<30;
    61     for(i=1;i<=26;i++){
    62         for(j=1;j<=10-n;j++)s1[j]=i;
    63         memcpy(s,s1,sizeof(s1));
    64         mins(ans,run(10));
    65     }
    66     printf("%d
    ",ans);
    67 }
    View Code
  • 相关阅读:
    79.Word Search
    78.Subsets
    77.Combinations
    75.Sort Colors
    74.Search a 2D Matrix
    73.Set Matrix Zeroes
    71.Simplify Path
    64.Minimum Path Sum
    63.Unique Paths II
    Docker 拉取 oracle 11g镜像配置
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5950956.html
Copyright © 2020-2023  润新知