1. 程式人生 > >洛谷P1941 飛揚的小鳥 01揹包+完全揹包

洛谷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