「Poetize5」GF弹钢琴

时间:2023-03-09 22:16:32
「Poetize5」GF弹钢琴
描述 Description

现在PianoEater有一架有52个白键和 36个黑键的钢琴,并且他要弹奏的曲子只需要按白键。在同一时刻,他只用弹奏一个音符。如果这个音符不移动大拇指就可以按到,那么他不需要耗费体力;否则 他需要花费sqrt(x)(下取整)的体力来移动手的位置(也就是移动大拇指的位置)。其中x代表移动前后大拇指的位置之差的绝对值。
现在有一首由N个音符组成的乐曲,每个音符用0~51之间的一个整数表示,分别对应了52个白键。0是最左边的键,51是最右边的键。PianoEater想知道他弹完这首曲子最少需要耗费多少体力。

题解:

题目说了好多废话。。。

理解了题意之后就是一个无脑DP

f[i][j][k]表示第 i 次左手大拇指在j,右手大拇指在k,然后暴力转移就行了,注意转移的范围。

代码:

 #include<cstdio>

 #include<cstdlib>

 #include<cmath>

 #include<cstring>

 #include<algorithm>

 #include<iostream>

 #include<vector>

 #include<map>

 #include<set>

 #include<queue>

 #include<string>

 #define inf 1000000000

 #define maxn 1050

 #define maxm 500+100

 #define eps 1e-10

 #define ll long long

 #define pa pair<int,int>

 #define for0(i,n) for(int i=0;i<=(n);i++)

 #define for1(i,n) for(int i=1;i<=(n);i++)

 #define for2(i,x,y) for(int i=(x);i<=(y);i++)

 #define for3(i,x,y) for(int i=(x);i>=(y);i--)

 #define mod 1000000007

 using namespace std;

 inline int read()

 {

     int x=,f=;char ch=getchar();

     while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}

     while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}

     return x*f;

 }
int l,r,n,ans,f[maxn][][],a[maxn]; int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); l=read();r=read();n=read();
for1(i,n)a[i]=read();
memset(f,,sizeof(f));
f[][l][r]=;
for0(i,n-)
for2(j,,)
for0(k,)
if(f[i][j][k]<inf)
{
for2(l,a[i+],a[i+]+)
{
if(l>)break;
f[i+][l][k]=min(f[i+][l][k],f[i][j][k]+(int)sqrt(abs(l-j)));
}
for3(l,a[i+],a[i+]-)
{
if(l<)break;
f[i+][j][l]=min(f[i+][j][l],f[i][j][k]+(int)sqrt(abs(k-l)));
}
}
ans=inf;
for2(i,,)
for0(j,)
ans=min(ans,f[n][i][j]);
printf("%d\n",ans); return ; }