洛谷P1941 飞扬的小鸟
好不容易写了这么长的注释当然要扔博客里……
学DP的第一天,想哭。
注意:由于愤怒的小鸟跳跃最大高度理论上是m最大值+x最大值,故f的第二维要开到两千以上。
1 #include<bits/stdc++.h> 2 #define ff(i,s,e) for(int i=s;i<=e;i++) 3 #define fff(i,s,e) for(int i=s;i>=e;i--) 4 using namespace std; 5 inline int read(){ 6 register int x=0,f=1;register char ch=getchar(); 7 while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();} 8 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 9 return x*f; 10 } 11 const int N=1e4+5,M=1e3+5; 12 int n,m,k; 13 int x[N],y[N]; 14 int low[N],high[N]; 15 bool vis[N]; 16 int f[N][2*M];//(i,j)最小次数 17 int main(){ 18 n=read(),m=read(),k=read(); 19 ff(i,1,n){ 20 x[i]=read(),y[i]=read(); 21 high[i]=m;low[i]=1; 22 } 23 int p,l,h; 24 ff(i,1,k){ 25 p=read();l=read();h=read(); 26 vis[p]=1; 27 low[p]=l+1,high[p]=h-1; 28 } 29 memset(f,0x3f,sizeof(f));//为取min做准备 30 ff(i,1,m) f[0][i]=0;//使i等于1算出正确答案 31 ff(i,1,n){ 32 ff(j,x[i]+1,m+x[i])//往上跳之后高度范围 33 f[i][j]=min(f[i-1][j-x[i]]+1,f[i][j-x[i]]+1);//上一秒往上跳和这一秒连跳结果取最小 34 ff(j,m+1,m+x[i])//跳冒了 ,最后纵坐标一定为m 35 f[i][m]=min(f[i][m],f[i][j]);//找最小方案 36 ff(j,1,m-y[i])//往下掉之后高度范围 37 f[i][j]=min(f[i][j],f[i-1][j+y[i]]);//和之前往上跳到当前位置(跳不到就是0x3f)得出的最优方案比取最小 38 ff(j,1,low[i]-1) f[i][j]=f[0][0]; 39 ff(j,high[i]+1,m) f[i][j]=f[0][0]; 40 //一定跳不到的地方赋统一值 41 } 42 int ans=f[0][0]; 43 ff(j,1,m){ 44 ans=min(ans,f[n][j]);//到达终点时枚举每个高度找最小的方案 45 } 46 if(ans<f[0][0]){printf("1\n%d",ans);return 0;}//若有最小方案 47 int i,j; 48 for(i=n;i>=1;i--){//从后往前搜索愤怒的小鸟能跳到的地方 49 for(j=1;j<=m;j++) 50 if(f[i][j]<f[0][0]){break;}//根据前面dp,若愤怒的小鸟跳不到则f[i][j]仍为0x3f 51 if(j<=m) break;//若第i列所有高度愤怒的小鸟都过不去,则此时的i就是鸟到达的最远处 52 } 53 ans=0; 54 for(int j=1;j<=i;j++) if(vis[j]) ans++; 55 return printf("0\n%d",ans),0; 56 }
                    
                
                
            
        
浙公网安备 33010602011771号