1. 程式人生 > >luogu1941 [NOIp2014]飛揚的小鳥 (dp)

luogu1941 [NOIp2014]飛揚的小鳥 (dp)

操作數 n) etc clr owb P20 轉移 bsp ans

設f[i][j]為到達(i,j)這個位置的最小操作數

就有$f[i][j]=min\{f[i-1][j+Y[i-1]],f[i-1][j-X[i-1]*k]+k\}$

然後考慮優化一下轉移:

對於一系列模x[i-1]相同的高度,它們都可以轉移到模x[i-1]相同的高度、而且在它們上邊的點,所以只要從下往上做,不斷地取一個最小值就可以了(會意 會意...)

要註意的是不管怎麽操作,只要操作完高度>M都會變成=M,而且還可以從M點一下還維持在M

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3
#define lowb(x) ((x)&(-(x))) 4 #define REP(i,n0,n) for(i=n0;i<=n;i++) 5 #define PER(i,n0,n) for(i=n;i>=n0;i--) 6 #define MAX(a,b) ((a>b)?a:b) 7 #define MIN(a,b) ((a<b)?a:b) 8 #define CLR(a,x) memset(a,x,sizeof(a)) 9 #define rei register int 10 using namespace std; 11 typedef long
long ll; 12 const int maxn=10010,maxm=1010; 13 14 inline ll rd(){ 15 ll x=0;char c=getchar();int neg=1; 16 while(c<0||c>9){if(c==-) neg=-1;c=getchar();} 17 while(c>=0&&c<=9) x=x*10+c-0,c=getchar(); 18 return x*neg; 19 } 20 21 int N,M,K; 22 int x[maxn],y[maxn];
23 int f[2][maxm],l[maxn],h[maxn],ans=1,cnt; 24 bool istube[maxn]; 25 26 int main(){ 27 // freopen("testdata.in","r",stdin); 28 rei i,j,k; 29 N=rd(),M=rd(),K=rd(); 30 for(i=0;i<N;i++) x[i]=rd(),y[i]=rd(); 31 for(i=0;i<=N;i++) l[i]=1,h[i]=M*2; 32 for(i=1;i<=K;i++){ 33 int a=rd(),b=rd(),c=rd(); 34 istube[a]=1; 35 l[a]=b+1;h[a]=c-1; 36 } 37 CLR(f,127);CLR(f[0],0); 38 bool b=1; 39 for(i=1;i<=N&&ans;i++){ 40 CLR(f[b],127); 41 for(j=l[i];j<=min(M,h[i])&&j+y[i-1]<=min(M,h[i-1]);j++){ 42 if(j+y[i-1]>=l[i-1]) f[b][j]=f[b^1][j+y[i-1]]; 43 } 44 for(j=l[i-1];j<l[i-1]+x[i-1]&&j<=min(M,h[i-1]);j++){ 45 int mm=f[b^1][j]; 46 // printf("!%d %d\n",j,mm); 47 for(k=1;j+x[i-1]*k<=h[i];k++){ 48 int jk=j+x[i-1]*k; 49 // printf("!!!%d %d\n",jk,mm); 50 bool re=0; 51 if(jk>M) jk=M,re=1; 52 if(jk>=l[i]) f[b][jk]=min(f[b][jk],mm+1); 53 ++mm;mm=min(mm,f[b^1][jk]); 54 if(re) break; 55 } 56 } 57 for(ans=0,j=l[i];j<=h[i];j++){ 58 // printf("%d %d %d\n",i,j,f[b][j]); 59 if(f[b][j]<=1e8) {ans=1;break;} 60 } 61 if(ans&&istube[i]) cnt++; 62 b^=1; 63 } 64 printf("%d\n",ans); 65 if(ans){ 66 ans=1e8; 67 for(i=l[N];i<=min(M,h[N]);i++) ans=min(ans,f[b^1][i]); 68 printf("%d\n",ans); 69 }else{ 70 printf("%d\n",cnt); 71 } 72 return 0; 73 }

luogu1941 [NOIp2014]飛揚的小鳥 (dp)