飞扬的小鸟 //借你题打下题解@laffey

xin_fu 2022-04-04 16:55:38 2022-04-09 20:01:25

首先,这是一道背包,嗯,背包就不难,所以不用题解,再见!!

好了,言归正传,这道题之所以是绿题,就是因为它太细了!!

首先是一个 m*n 的一个平面,求到终点所需点击屏幕的最小值。

那我们不妨用f(i,j)来表示到坐标(i,j)所需点击屏幕的最小值。

然后怎么往后推呢?//用laffey的话来说“lao zi bu hui”

对于每一个横坐标i来说,它下一个坐标一定是i+1(废话,要不还能是i呢)

然后对于每一个i来说,它有两种状态,即点击屏幕&&不点击屏幕

所以就有了这个递推式

f[i][j]=min(f[i][j],min(f[i-1][j-x],f[i][j-x]))//没错,它下一个坐标真的可以是i
f[i][j]=min(f[i][j],f[i-1][j+y])

其实点击屏幕就是一个完全背包,不点击就是一个01背包

递推式已经有了,还A不了吗?后面你还要看?

好吧,然后是处理管道是吧。

这玩意非常好处理,你不是有管道的坐标吗,在递推到管道的时候把它给定义成0x3f3f3f3f就OK了

什么,你看到这里还A不了?是不是应该反思一下。

后面是什么问题,我猜猜啊!

是不是不会找能过几个管道啊,行了代码给你,剩下的自己写吧。

int mn=mk,cnt=k;
for(int i=n;i>=1;i--)
{
	for(int j=l[i]+1;j<g[i];j++)if(f[i][j]<mk)mn=min(mn,f[i][j]);//l[i]表示每一个的最低点,平时是0,管道处是管道的下边高度。g[i]是上边的
	if(mn!=mk)break;
	if(g[i]<=m)cnt--;
}
if(cnt==k)cout<<1<<endl<<mn;
else cout<<0<<endl<<cnt;

什么,你还没A!!!

又是什么问题?

没处理到 j==m 吗?这你不能,至少不应该吧。

行了代码拿去。

for(int j=1;j<=m;j++)
{
	if(j>h[i].x)
	f[i][j]=min(f[i][j],min(f[i-1][j-h[i].x]+1,f[i][j-h[i].x]+1));
	if(j==m)
	{
	for(int t=m-h[i].x;t<=m;t++)
	  f[i][j]=min(f[i][j],min(f[i][t]+1,f[i-1][t]+1));
	}
}

你不会还没A吧,又是什么问题啊?

哦,你不会先处理的下降吧!

你先下降的话,在上升是不是有点问题啊;

没错,就是这玩意(f(i,j)=f(i,j-x))

好了,这题也没啥好说的了,代码给你,剩下还有什么问题自己找吧。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int n,k,m;
struct yzy{
	int x,y;
}h[N];
const int mk=0x3f3f3f3f;
int l[N],g[N];
int f[10010][1010];
int main()
{
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
		cin>>h[i].x>>h[i].y;
	for(int i=1;i<=n;i++)
	{
		l[i]=0;
		g[i]=m+1;
	}
	for(int i=1;i<=k;i++)
	{
		int p,a,s;
		cin>>p>>a>>s;
		l[p]=a;g[p]=s;
	}
	memset(f,0x3f,sizeof(f));
	for(int i=1;i<=m;i++)
		f[0][i]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(j>h[i].x)
			f[i][j]=min(f[i][j],min(f[i-1][j-h[i].x]+1,f[i][j-h[i].x]+1));
			if(j==m)
			{
				for(int t=m-h[i].x;t<=m;t++)
				f[i][j]=min(f[i][j],min(f[i][t]+1,f[i-1][t]+1));
			}
		}
		for(int j=g[i]-1;j>=l[i]+1;j--)
		{
			if(m-j>=h[i].y)
			{
				f[i][j]=min(f[i][j],f[i-1][j+h[i].y]);
			}
		}
		for(int j=1;j<=l[i];j++)
			f[i][j]=mk;
		for(int j=m;j>=g[i];j--)
			f[i][j]=mk;
	}
	int mn=mk,cnt=k;
	for(int i=n;i>=1;i--)
	{
		for(int j=l[i]+1;j<g[i];j++)if(f[i][j]<mk)mn=min(mn,f[i][j]);
		if(mn!=mk)break;
		if(g[i]<=m)cnt--;
	}
	if(cnt==k)cout<<1<<endl<<mn;
	else cout<<0<<endl<<cnt;
	return 0;
}

共 2 条回复

xin_fu

还有谁题?QAQ

Laffey

nb^{nb^{nb^{nb}_{nb}}_{nb^{nb}_{nb}}}_{nb^{nb^{nb}_{nb}}_{nb^{nb}_{nb}}} 所以为什么要接我题