【[NOIP2014 Day1 T3]飞扬的小鸟】背包啦啦啦

第一次看还是感觉很难的。。。仔细分析起来,发现自己还是太弱了。。。

传送门:https://www.luogu.org/problemnew/show/P1941

状态;f[i][j]第i格,达到高度j所需最小的点击次数

70%分 :  f[i][j] = min: f[i-1][j+y[i]] , f[i-1][j-k*x[i]] 选择点还是不点

点向上k个x[i],不点下降y[i],

100%分  f[i][j] = min: f[i-1][j+y[i]], min (f[i-1][j-x[i]] ,f[i][j-x[i]] )

但是多加了个k会超时。我们可以想到将点击多次转化为一个完全背包,那么就可以从1扫到m,转化为f[i][j-x[i]]

注意处理跳超m,水管直接处理成设置不能到达的地方设成dp[i][j]=inf就好。

这样我们就将题目上升处理成了完全背包,下降处理为了01背包。

Intersting!来玩啊! 游戏传送门:http://www.newuser.top/2018/03/31/%E3%80%90%E6%9C%89%E8%B6%A3%E3%80%91%E9%A3%9E%E6%89%AC%E7%9A%84%E5%B0%8F%E9%B8%9F/

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int iii = 1000000000;
int n,m,k;
int x[10005],y[10005],low[10005],high[10005],youg[10005];
int dp[10005][2005];
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++) 
	{
		scanf("%d%d",&x[i],&y[i]);
		high[i]=m; low[i]=1;
	}
	int a,b,c;
	for(int i=1;i<=k;i++) 
	{
		scanf("%d%d%d",&a,&b,&c); 
		youg[a]=1; low[a]=b+1; high[a]=c-1;
	}
	memset(dp,inf,sizeof dp);
	for(int i=0;i<=m;i++) dp[0][i]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=x[i]+1;j<=m+x[i];j++)
		{
			dp[i][j]=min(dp[i-1][j-x[i]]+1,dp[i][j-x[i]]+1);
		}
		for(int j=m+1;j<=m+x[i];j++) dp[i][m]=min(dp[i][j],dp[i][m]);
		for(int j=m-y[i];j>=1;j--)
		{
			dp[i][j]=min(dp[i][j],dp[i-1][j+y[i]]);
		}
		for(int j=0;j<low[i];j++) dp[i][j]=inf;
		for(int j=m;j>high[i];j--) dp[i][j]=inf;
	}
	int ans=inf;
	for(int i=low[n];i<=high[n];i++) ans=min(ans,dp[n][i]);
	if(ans<iii){ printf("1\n%d",ans); return 0; }
	else printf("0\n");
	ans=0; int kk;
	for(int i=1;i<=n;i++)
	{
		kk=1;
		for(int j=low[i];j<=high[i];j++)
		{
			if(dp[i][j]<iii) { kk=0; break; }
		}
		if(kk==1) { printf("%d",ans); return 0; }
		if(youg[i]==1) ans++;
	}
}

 

 

posted @ 2018-04-01 10:58  Newuser233  阅读(10)  评论(0)    收藏  举报