描述 Description
现在PianoEater有一架有52个白键和 36个黑键的钢琴,并且他要弹奏的曲子只需要按白键。在同一时刻,他只用弹奏一个音符。如果这个音符不移动大拇指就可以按到,那么他不需要耗费体力;否则 他需要花费sqrt(x)(下取整)的体力来移动手的位置(也就是移动大拇指的位置)。其中x代表移动前后大拇指的位置之差的绝对值。
现在有一首由N个音符组成的乐曲,每个音符用0~51之间的一个整数表示,分别对应了52个白键。0是最左边的键,51是最右边的键。PianoEater想知道他弹完这首曲子最少需要耗费多少体力。
题解:
题目说了好多废话。。。
理解了题意之后就是一个无脑DP
f[i][j][k]表示第 i 次左手大拇指在j,右手大拇指在k,然后暴力转移就行了,注意转移的范围。
代码:
1 #include<cstdio> 2 3 #include<cstdlib> 4 5 #include<cmath> 6 7 #include<cstring> 8 9 #include<algorithm> 10 11 #include<iostream> 12 13 #include<vector> 14 15 #include<map> 16 17 #include<set> 18 19 #include<queue> 20 21 #include<string> 22 23 #define inf 1000000000 24 25 #define maxn 1050 26 27 #define maxm 500+100 28 29 #define eps 1e-10 30 31 #define ll long long 32 33 #define pa pair<int,int> 34 35 #define for0(i,n) for(int i=0;i<=(n);i++) 36 37 #define for1(i,n) for(int i=1;i<=(n);i++) 38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 42 43 #define mod 1000000007 44 45 using namespace std; 46 47 inline int read() 48 49 { 50 51 int x=0,f=1;char ch=getchar(); 52 53 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 54 55 while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();} 56 57 return x*f; 58 59 } 60 int l,r,n,ans,f[maxn][55][55],a[maxn]; 61 62 int main() 63 64 { 65 66 freopen("input.txt","r",stdin); 67 68 freopen("output.txt","w",stdout); 69 70 l=read();r=read();n=read(); 71 for1(i,n)a[i]=read(); 72 memset(f,60,sizeof(f)); 73 f[0][l][r]=0; 74 for0(i,n-1) 75 for2(j,4,51) 76 for0(k,47) 77 if(f[i][j][k]<inf) 78 { 79 for2(l,a[i+1],a[i+1]+8) 80 { 81 if(l>51)break; 82 f[i+1][l][k]=min(f[i+1][l][k],f[i][j][k]+(int)sqrt(abs(l-j))); 83 } 84 for3(l,a[i+1],a[i+1]-8) 85 { 86 if(l<0)break; 87 f[i+1][j][l]=min(f[i+1][j][l],f[i][j][k]+(int)sqrt(abs(k-l))); 88 } 89 } 90 ans=inf; 91 for2(i,4,51) 92 for0(j,47) 93 ans=min(ans,f[n][i][j]); 94 printf("%d\n",ans); 95 96 return 0; 97 98 }
时间: 2024-10-28 16:04:20