#线性动态规划,背包#JZOJ 3932 洛谷 1941 飞扬的小鸟

题目


分析

可以把它看成一个背包
下降就是01背包,上升就是完全背包,然后超过范围的取最大值,时间复杂度 O ( n m ) O(nm) O(nm)


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=10011;
int n,m,k,up[N],dw[N],ulm[N],dlm[N],is_tune[N],dp[N][N/5];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans; 
}
inline signed min(int a,int b){return a<b?a:b;}
signed main(){
    n=iut(),m=iut(),k=iut();
    for (rr int i=1;i<=n;++i) up[i]=iut(),dw[i]=iut(),ulm[i]=m+1,dlm[i]=0;
    for (rr int i=1;i<=k;++i){
    	rr int x=iut(),l=iut(),r=iut();
    	is_tune[x]=1,dlm[x]=l,ulm[x]=r;
	}
	memset(dp,42,sizeof(dp));
	for (rr int i=1;i<=m;++i) dp[0][i]=0;
	for (rr int i=1;i<=n;++i){
		for (rr int j=1+up[i];j<=m+up[i];++j)
		     dp[i][j]=min(dp[i][j-up[i]],dp[i-1][j-up[i]])+1;
		for (rr int j=m+1;j<=m+up[i];++j) dp[i][m]=min(dp[i][m],dp[i][j]);
		for (rr int j=1;j<=m-dw[i];++j) dp[i][j]=min(dp[i][j],dp[i-1][j+dw[i]]);
		for (rr int j=1;j<=dlm[i];++j) dp[i][j]=dp[0][0];
		for (rr int j=ulm[i];j<=m;++j) dp[i][j]=dp[0][0];
	}
	rr int ans=dp[0][0];
	for (rr int i=1;i<=m;++i) ans=min(ans,dp[n][i]);
	if (ans<dp[0][0]) return !printf("1\n%d",ans);
	else{
		rr int ii,flag=0; ans=0;
		for (ii=n;ii>=1;--ii){
			for (rr int j=1;j<=m;++j){
			    if (dp[ii][j]>=dp[0][0]) continue;
			    flag=1; break;
		    }
		    if (flag) break;
		}
		for (rr int i=1;i<=ii;++i) ans+=is_tune[i];
		return !printf("0\n%d",ans); 
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值