题目大意:
题目链接:https://jzoj.net/senior/#main/show/5907
题目图片:
http://wx4.sinaimg.cn/mw690/0060lm7Tly1fwqa674nrcj30jb0e93z2.jpg
http://wx1.sinaimg.cn/mw690/0060lm7Tly1fwqa674c41j30ja0ctjrl.jpg
http://wx2.sinaimg.cn/mw690/0060lm7Tly1fwqa6743zij30jf0ardfv.jpg
有 n n n个木桩和 m m m种轻功,第 i i i种轻功要花费 t [ i ] t[i] t[i]的时间往前 f [ i ] f[i] f[i]个梅花桩。有些轻功不可以经过(含从上面飞过)一些木桩。求从 0 0 0到 n n n的最小时间。切换轻功需要 s s s的时间。
思路:
很明显是
D
P
DP
DP。
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示跳到第
i
i
i个梅花桩,准备用
j
j
j轻功跳下一个梅花桩的最小时间花费。
那么很明显我们要枚举是用哪一个轻功飞到第
i
i
i个梅花桩的。那么再在第三重循环
k
k
k枚举。
那么如果
j
=
k
j=k
j=k,就不用花费
s
s
s去切换,就有:
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
]
,
f
[
i
−
a
[
j
]
.
f
]
[
k
]
+
a
[
j
]
.
t
)
f[i][j]=min(f[i][j],f[i-a[j].f][k]+a[j].t)
f[i][j]=min(f[i][j],f[i−a[j].f][k]+a[j].t)
如果
j
!
=
k
j!=k
j!=k,那么久在后面加一个
s
s
s即可。
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
]
,
f
[
i
−
a
[
j
]
.
f
]
[
k
]
+
a
[
j
]
.
t
+
s
)
f[i][j]=min(f[i][j],f[i-a[j].f][k]+a[j].t+s)
f[i][j]=min(f[i][j],f[i−a[j].f][k]+a[j].t+s)
答案就是
m
i
n
(
f
[
n
]
[
i
]
)
(
1
≤
i
≤
m
)
min(f[n][i])(1\leq i\leq m)
min(f[n][i])(1≤i≤m)
时间复杂度
O
(
n
2
m
)
O(n^2m)
O(n2m),常数不是很大,可以过掉。
代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#define ll long long
#define N 510
#define M 110
using namespace std;
int n,m,s,q;
bool p[N][M];
ll f[N][M];
struct node
{
int t,f;
}a[N];
bool check(int l,int r,int x) //判断飞过的梅花桩中是否有不允许用这种轻功过的
{
for (int i=l;i<=r;i++)
if (p[i][x]==1) return 0;
return 1;
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for (int i=1;i<=m;i++)
scanf("%d%d",&a[i].f,&a[i].t);
scanf("%d",&q);
int x,y;
for (int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
p[x][y]=1;
}
for (int i=0;i<=n;i++)
for (int j=1;j<=m;j++)
f[i][j]=1e17;
for (int i=1;i<=m;i++)
if (!p[0][i])
f[0][i]=0; //初始化
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (i-a[j].f>=0&&check(i-a[j].f,i,j))
for (int k=1;k<=m;k++)
if (j!=k)
f[i][j]=min(f[i][j],f[i-a[j].f][k]+(ll)a[j].t+(ll)s);
else
f[i][j]=min(f[i][j],f[i-a[j].f][k]+(ll)a[j].t);
ll ans=1e17;
for (int i=1;i<=m;i++)
if (!p[n][i])
ans=min(ans,f[n][i]);
if (ans<1e17) cout<<ans;
else printf("-1");
return 0;
}