5907. 【NOIP2018模拟10.16】轻功()

题目大意:

一共有 n 个木桩,要求从起点(0)开始,经过所有梅花桩,恰好到达终点 n,尊者神高达一共会 k 种门派的轻功,不同门派的轻功经过的梅花桩数不同,花费时间也不同。但是尊者神高达一次只能使用一种轻功,当他使用别的门派的轻功时,需要花费 W 秒切换(开始时可以是任意门派,不需要更换时间)。由于尊者神高达手残,所以经过某些梅花桩(包括起点和终点)时他不能使用一些门派的轻功。尊者神高达想知道他最快多久能到达终点如果无解则输出-1。

思路:

很显然代价只和到第几个柱子和上次用的什么功法有关,然后跳的时候中间不能有特殊柱子,所以我们一开始预处理哪些点可以走,然后枚举柱子和功法直接dp就可以了。

程序:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int N=1005;
LL ans,n,k,W,a[N],w[N],q,x,p;
LL h[N][N],f[N][N];
int main(){
	freopen("qinggong.in","r",stdin);
	freopen("qinggong.out","w",stdout);
	scanf("%lld%lld%lld",&n,&k,&W);
	for (LL i=1;i<=k;i++) scanf("%lld%lld",&a[i],&w[i]);
	scanf("%lld",&q);
	for (LL i=1;i<=q;i++) {
		scanf("%lld%lld",&x,&p);
		h[x][p]=1;
		for (LL j=1;j<=a[p];j++) h[x+j][p]=1;
	}
	memset(f,31,sizeof(f));
	for (LL i=1;i<=k;i++) f[0][i]=0;
	for (LL i=1;i<=n;i++)
	 for (LL j=1;j<=k;j++)
	  if (!h[i][j]){
	  	for (LL ii=1;ii<=k;ii++)
	  		if (ii==j&&i-a[j]>=0) f[i][j]=min(f[i][j],f[i-a[j]][ii]+w[j]);
	  	 		else if (i-a[j]>=0) f[i][j]=min(f[i][j],f[i-a[j]][ii]+w[j]+W);	
	  }
	ans=12345678900;
	for (LL i=1;i<=k;i++) ans=min(ans,f[n][i]);
	if (ans==12345678900) printf("-1");
				else printf("%lld",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值