题目翻译中的错误及补充
输入格式
输入包含多组数据,每组数据占一行。一组数据中包含若干个以空格隔开的整数,以 0 0 0 结尾。最后有一行一个单独的 0 0 0,表示数据输入完毕。
输出格式
对于每一组数据,输出一行表示答案。
样例输入
1 2 3 4 1 2 3 3 4 2 0
1 4 3 4 3 2 3 2 1 0
0
样例输出
22
18
箭头的布局应为:
思路
容易看出是 dp
。用
d
p
i
,
j
(
j
∈
{
0
,
1
,
2
,
3
,
4
}
)
dp_{i,j}(j\in\{0,1,2,3,4\})
dpi,j(j∈{0,1,2,3,4}) 表示到了第
i
i
i 个箭头,除了踩在
a
i
a_i
ai(箭头所示位置)上的脚之外另一只脚踩在
j
j
j 的位置。转移时分类讨论(用
i
i
i 更新
i
+
1
i+1
i+1):
- 踩在 a i a_i ai 上的脚刚好在 a i + 1 a_{i+1} ai+1 上,再踩一次,耗费 1 1 1 点体力。
- 踩在 j j j 上的脚刚好在 a i + 1 a_{i+1} ai+1 上,再踩一次,耗费 1 1 1 点体力。
- 移动踩在 a i a_i ai 上的脚去踩 a i + 1 a_{i+1} ai+1。
- 移动踩在 j j j 上的脚去踩 a i + 1 a_{i+1} ai+1。
为了计算一个位置到另一个位置的体力耗费,我使用了 cal
函数计算,cal
同样要分类讨论:
- 从 0 0 0 到其他位置: 2 2 2。
- 从 x x x 到 x + 1 x+1 x+1 或者从 4 4 4 到 1 1 1,从 1 1 1 到 4 4 4: 3 3 3。
- 其他情况: 4 4 4。
转移方程:
{
d
p
i
+
1
,
j
=
min
(
d
p
i
+
1
,
j
,
d
p
i
,
j
+
1
)
a
i
=
a
i
+
1
d
p
i
+
1
,
a
i
=
min
(
d
p
i
+
1
,
a
i
,
d
p
i
,
j
+
1
)
j
=
a
i
+
1
d
p
i
+
1
,
j
=
min
(
d
p
i
+
1
,
j
,
d
p
i
,
j
+
c
a
l
(
a
i
,
a
i
+
1
)
)
,
d
p
i
+
1
,
a
i
=
min
(
d
p
i
+
1
,
a
i
,
d
p
i
,
j
+
c
a
l
(
j
,
a
i
+
1
)
)
a
i
≠
a
i
+
1
且
j
≠
a
i
+
1
\begin{cases} dp_{i+1,j}=\min(dp_{i+1,j},dp_{i,j}+1) \quad a_i=a_{i+1}\\ dp_{i+1,a_i}=\min(dp_{i+1,a_i},dp_{i,j}+1)\quad j=a_{i+1}\\ dp_{i+1,j}=\min(dp_{i+1,j},dp_{i,j}+cal(a_i,a_{i+1})),dp_{i+1,a_i}=\min(dp_{i+1,a_i},dp_{i,j}+cal(j,a_{i+1}))\quad a_i \neq a_{i+1} 且 j\neq a_{i+1} \end{cases}
⎩
⎨
⎧dpi+1,j=min(dpi+1,j,dpi,j+1)ai=ai+1dpi+1,ai=min(dpi+1,ai,dpi,j+1)j=ai+1dpi+1,j=min(dpi+1,j,dpi,j+cal(ai,ai+1)),dpi+1,ai=min(dpi+1,ai,dpi,j+cal(j,ai+1))ai=ai+1且j=ai+1
边界情况:
d
p
0
,
0
=
0
,
a
0
=
0
dp_{0,0}=0,a_0=0
dp0,0=0,a0=0。这样就把初始状态设为了站在
0
,
0
0,0
0,0。
答案:
min
d
p
t
o
t
,
i
(
i
∈
{
0
,
1
,
2
,
3
,
4
}
)
\min dp_{tot,i}(i\in\{0,1,2,3,4\})
mindptot,i(i∈{0,1,2,3,4}),
t
o
t
tot
tot 表示箭头个数。
注意:每组数据要把
d
p
i
,
j
dp_{i,j}
dpi,j 重新设为 0x3f3f3f3f
;
t
o
t
tot
tot 设为
0
0
0,重新开始统计箭头个数。
代码
#include<bits/stdc++.h>
using namespace std;
int tot,a[100005],dp[100005][5];
int cal(int x,int y){
if(x==0||y==0) return 2;
if(abs(x-y)==1) return 3;
if(x==1&&y==4||x==4&&y==1) return 3;
return 4;
}
int main(){
while(1){
tot=0;
cin>>a[++tot];
if(a[tot]==0) break;
while(cin>>a[++tot])
if(a[tot]==0){
tot--;
break;
}
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=0;i<tot;i++)
for(int j=0;j<=4;j++){
if(a[i+1]==a[i]) dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1);
else if(a[i+1]==j) dp[i+1][a[i]]=min(dp[i+1][a[i]],dp[i][j]+1);
else{
dp[i+1][j]=min(dp[i+1][j],dp[i][j]+cal(a[i],a[i+1]));
dp[i+1][a[i]]=min(dp[i+1][a[i]],dp[i][j]+cal(j,a[i+1]));
}
}
cout<<min(min(min(dp[tot][1],dp[tot][2]),min(dp[tot][3],dp[tot][4])),dp[tot][0])<<endl;
}
return 0;
}