【[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++;
}
}

浙公网安备 33010602011771号