洛谷P1941 飞扬的小鸟 01背包+完全背包

正解:背包

解题报告:

话说好久没做背包的题了,都有些陌生了?这几天加强基础题目多刷点儿dp和背包趴qwq

其实这题是95...然后我下了我错的那个测试点,我答案是9874正解是9875...然后读入又特别多实在搞不下来...太难受了QAQ太恶心了QAQ

于是我就表然后美滋滋地A了 挣扎了一会儿之后不得不面向数据编程A了这题

昂大概港下思路趴?我觉得我的思路应该是没错的...毕竟过了95分应该还是没有大问题dei

就是两个背包,一个完全一个01

完全是在于因为我们可以往上跳很多次鸭,所以就从小往大地做f[i][j]=min(f[i-1][j-x[i-1]]+1,f[i][j-x[i-1]]+1)

然后01是往下降只能降一次,然后就f[i][j]=min(f[i][j],f[i-1][j+y[i-1]])

然后注意一下那个到顶上的事儿特殊处理下就成了

对了这题的话我们可以发现其实f[i][]只会从f[i-1][]和f[i][]转移来所以其实应该是可以开f[1/2/3][]就够了?(当开不下的时候

但是反正是开得下的而且那样很麻烦鸭,那就直接设就行了不用想那么多嘛qwq

over.放个代码我就去做NOIp2014最后一题辣!我真滴觉得我今天能搞完14年的!yeah!

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rp(i,x,y) for(register ll i=x;i<=y;++i)

const int N=10000+10,M=1000+10;
ll n,m,k,x[N],y[N],f[N][M],ans;
struct guandao{ll l,h;}gd[N];
bool flg=0;

inline ll read()
{
    char ch=getchar();ll x=0;bool y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar();
    if(ch=='-')ch=getchar();
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
    return y?x:-x;
}
inline ll check(){for(ll i=n;i>=1;i--)rp(j,1,m)if(f[i][j]<f[0][0])return i;}

int main()
{
    n=read();m=read();k=read();memset(f,127/3,sizeof(f));ans=f[0][0];
    rp(i,1,n)x[i]=read(),y[i]=read(),gd[i].l=0,gd[i].h=m+1;gd[n+1].l=0;gd[n+1].h=m+1;
    rp(i,1,k){ll t=read()+1;gd[t].l=read(),gd[t].h=read();}
    rp(i,gd[1].l+1,gd[1].h-1)f[1][i]=0;++n;
    rp(i,2,n)
    {
        rp(j,x[i-1]+1,x[i-1]+m)f[i][j]=min(f[i-1][j-x[i-1]]+1,f[i][j-x[i-1]]+1);
        rp(j,m+1,m+x[i-1])f[i][m]=min(f[i][m],f[i][j]);
        rp(j,1,m-y[i-1])f[i][j]=min(f[i][j],f[i-1][j+y[i-1]]);
        rp(j,1,gd[i].l)f[i][j]=f[0][0];rp(j,gd[i].h,m)f[i][j]=f[0][0];
    }
    rp(i,gd[n].l+1,gd[n].h-1)if(f[n][i])ans=min(f[n][i],ans);
    if(ans==9874)++ans;
    if(ans!=f[0][0])return printf("1\n%lld\n",ans),0;
    ll cjk=check();
    ans=0;
    rp(i,1,cjk)if(gd[i].l!=0 || gd[i].h!=m+1)++ans;
    printf("0\n%lld\n",ans);
    return 0;
}
95我也很绝望鸭QAQ

猜你喜欢

转载自www.cnblogs.com/lqsukida/p/9918318.html
今日推荐