[P1541 NOIP2010 提高组] 乌龟棋 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
问题描述:一行数字,一个乌龟在位置1处,有m张卡牌,卡牌上有1,2,3,4四个数字,使用完这个卡牌,乌龟可以向前爬行相应的格子,每一格都有不同的权重。问经过合理的顺序得到的最大的价值和,保证巧合到达终点N。
思路:数据范围很小。可以用四维dp,状态表示为用了i个卡牌1,用了j个卡牌2,用了k个卡牌3,用了z个卡牌4可以得到的最大价值和。
状态转移方程:
F
(
i
,
j
,
k
,
z
)
=
{
i
≠
0
m
a
x
(
F
(
i
,
j
,
k
,
z
)
,
F
(
i
−
1
,
j
,
k
,
z
)
+
v
a
l
)
j
≠
0
m
a
x
(
F
(
i
,
j
,
k
,
z
)
,
F
(
i
,
j
−
1
,
k
,
z
)
+
v
a
)
k
≠
0
m
a
x
(
F
(
i
,
j
,
k
,
z
)
,
F
(
i
,
j
,
k
−
1
,
z
)
+
v
a
l
)
z
≠
0
m
a
x
(
F
(
i
,
j
,
k
,
z
)
,
F
(
i
,
j
,
k
,
z
−
1
)
+
v
a
l
)
v
a
l
=
a
[
i
∗
1
+
j
∗
2
+
k
∗
3
+
z
∗
4
+
1
]
F(i,j,k,z) = \begin{cases} i \not= 0 \quad max(F(i,j,k,z), F(i-1,j,k,z) + val) \\ j \not= 0 \quad max(F(i,j,k,z), F(i,j-1,k,z) + va) \\ k \not= 0 \quad max(F(i,j,k,z), F(i,j,k-1,z) + val) \\ z \not= 0 \quad max(F(i,j,k,z), F(i,j,k,z-1) + val) \\ val = a[ i * 1 + j * 2 + k * 3 + z*4 + 1] \end{cases}
F(i,j,k,z)=⎩
⎨
⎧i=0max(F(i,j,k,z),F(i−1,j,k,z)+val)j=0max(F(i,j,k,z),F(i,j−1,k,z)+va)k=0max(F(i,j,k,z),F(i,j,k−1,z)+val)z=0max(F(i,j,k,z),F(i,j,k,z−1)+val)val=a[i∗1+j∗2+k∗3+z∗4+1]
边界:
F
(
0
,
0
,
0
,
0
)
=
a
[
0
]
F(0,0,0,0) = a[0]
F(0,0,0,0)=a[0]
目标:
F
(
m
i
i
[
1
]
,
m
i
i
[
2
]
,
m
i
i
[
3
]
,
m
i
i
[
4
]
)
F(mii[1], mii[2], mii[3], mii[4])
F(mii[1],mii[2],mii[3],mii[4])
AC代码:
int f[N][N][N][N];
int a[N];
void inpfile();
void solve() {
map<int,int> mii;
int n,m; cin>>n>>m;
rep(i,1,n) cin>>a[i];
rep(i,1,m) {
int t; cin>>t; mii[t]++;
}
f[0][0][0][0] = a[1];
rep(i,0,mii[1]) {
rep(j,0,mii[2]) {
rep(k,0,mii[3]) {
rep(z,0,mii[4]) {
int idx = i + 2 * j + 3 * k + 4 * z + 1;
int val = a[idx];
// cout<<val;
if(i) f[i][j][k][z] = max(f[i][j][k][z], f[i-1][j][k][z] + val);
if(j) f[i][j][k][z] = max(f[i][j][k][z], f[i][j-1][k][z] + val);
if(k) f[i][j][k][z] = max(f[i][j][k][z], f[i][j][k-1][z] + val);
if(z) f[i][j][k][z] = max(f[i][j][k][z], f[i][j][k][z-1] + val);
}
}
}
}
cout<<f[ mii[1]][ mii[2]][ mii[3]][ mii[4]];
}