1. 程式人生 > >P1941 飛揚的小鳥(揹包)

P1941 飛揚的小鳥(揹包)

P1941 飛揚的小鳥

細節題

上升是完全揹包

下降是01揹包

(陣列訪問越界本機怎麼能過???(大霧))

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cctype>
 5 #define re register
 6 using namespace std;
 7 void read(int &x){
 8     char c=getchar();x=0;
 9     while(!isdigit(c)) c=getchar();
10 while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar(); 11 } 12 int min(int &a,int &b){return a<b?a:b;} 13 int max(int &a,int &b){return a>b?a:b;} 14 void swap(int &a,int &b){a^=b;b^=a;a^=b;} 15 #define N 10002 16 int ans=2e9,n,m,k,f[N][2002]; 17 int a[N],b[N],l[N],r[N],v[N];
18 int main(){ 19 read(n); read(m); read(k); int q1,q2,q3; 20 for(re int i=1;i<=n;++i){ 21 read(a[i]); read(b[i]); 22 l[i]=1; r[i]=m;//下/上界 23 } 24 for(re int i=1;i<=k;++i){ 25 read(q1); read(q2); read(q3); 26 if(q2>q3) swap(q2,q3); 27 l[q1]=q2+1
; r[q1]=q3-1; v[q1]=1;//v:當前列是否有管子 28 } 29 memset(f,63,sizeof(f)); int inf=f[0][0],tot=0; 30 for(re int i=1;i<=m;++i) f[0][i]=0; 31 for(re int i=1;i<=n;++i){ 32 for(re int j=a[i]+1;j<=m+a[i];++j) //上升完全揹包 33 f[i][j]=min(f[i][j-a[i]],f[i-1][j-a[i]])+1; 34 for(re int j=m+1;j<=m+a[i];++j) //飛到m時特判 35 f[i][m]=min(f[i][m],f[i][j]); 36 for(re int j=1;j<=m-b[i];++j)//下降01揹包 37 f[i][j]=min(f[i][j],f[i-1][j+b[i]]); 38 for(re int j=1;j<l[i];++j) f[i][j]=inf;//其他地方不能飛 39 for(re int j=r[i]+1;j<=m;++j) f[i][j]=inf; 40 bool gg=1; 41 for(re int j=l[i];j<=r[i];++j) gg=(gg&&f[i][j]>=inf); 42 if(gg){printf("0\n%d",tot); return 0;}//無法飛下去 43 tot+=v[i]; 44 } 45 for(re int i=l[n];i<=r[n];++i) ans=min(ans,f[n][i]); 46 printf("1\n%d",ans); 47 return 0; 48 }
View Code