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 }