洛谷P1941 飞扬的小鸟 动态规划

洛谷P1941 飞扬的小鸟
动态规划
这道题主要要注意一下飞到m以上之后高度还是 m
这个就要在判断一下
比较直接暴力的动归 是 O(N^3)
f[ i ][ j ] 到 i ,j 这个位置 所需要的最少点击次数
如果不能到,就是无限大
f[ i ][ j ] = min(f[ i-1 ][ j-up[i-1] ] +1 , f[ i-1 ][ j+down[i-1] ] )
因为可以向上飞无限次 这其实就相当于是无限背包
然后 f[ i ][ j ] 就可以从 f[ i ][ j-up[ i-1 ] ] 转移过来 枚举正向
相当于 完全背包

 

 1 #include <bits/stdc++.h> 
 2 using namespace std ; 
 3 
 4 const int N = 1e4+11,M = 1e3+11,inf = 0x3f3f3f3f ; 
 5 int n,m,ans,s,u,v,k ; 
 6 int up[N],down[N],top[N],bot[N],f[N][M] ; 
 7 
 8 inline int read() 
 9 {
10     int x = 0 , f = 1 ; 
11     char ch = getchar() ; 
12     while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 
13     while(ch>='0'&&ch<='9') { x = x * 10+ch-48 ; ch = getchar() ; } 
14     return x * f ; 
15 } 
16 
17 int main() 
18 {
19     n = read() ; m = read() ; k = read() ; 
20     for(int i=0;i<n;i++) 
21         up[ i ] = read() , down[ i ] = read() ; 
22     for(int i=0;i<=n;i++) 
23         top[ i ] = m+1 , bot[ i ] = 0 ; 
24     for(int i=1;i<=k;i++) 
25     {
26         s = read() ; u = read() ; v = read() ; 
27         bot[ s ] = u ; 
28         top[ s ] = v ; 
29     } 
30     
31     memset(f,0x3f,sizeof(f)) ;   //  初始化 无限大 
32     for(int i=1;i<=m;i++) f[ 0 ][ i ] = 0 ; 
33     for(int i=1;i<=n;i++) 
34     {
35         for(int j=1;j<=m;j++) 
36         {
37             u = j - up[ i-1 ] ; 
38             if( u>bot[i-1]&&u<top[i-1] ) 
39                 f[ i ][ j ] = min(f[i][j],f[i-1][u]+1) ; 
40             if( u>0 ) 
41                 f[ i ][ j ] = min(f[i][j],f[i][u]+1) ; 
42         }
43         for(int j=m;j>=m-up[i-1]&&j>=1 ; j--)       //   特殊 判断 高度 为 n 的情况     
44         //for(int j=max(1,m-up[i-1]);j<=m;j++)                                       //应该无需倒序的吧 
45         {
46             f[ i ][ m ] = min(f[i][m],f[i][j]+1) ; 
47             if( j>bot[ i-1 ]&&j<top[ i-1 ] ) 
48                 f[ i ][ m ] = min(f[ i ][ m ],f[ i-1 ][ j ]+1) ; 
49         }
50         for(int j=1;j<=m;j++) 
51         {
52             u = j + down[ i-1 ] ; 
53             if( u>bot[i-1] && u<top[i-1] ) 
54                 f[ i ][ j ] = min(f[ i ][ j ],f[ i-1 ][ u ]) ;     
55         } 
56     } 
57     ans = inf ; 
58     for(int i=1;i<=m;i++) 
59         if(f[ n ][ i ] < ans ) ans = f[ n ][ i ] ; 
60     if(ans!=inf) 
61     {
62         printf("1\n%d\n",ans) ; 
63         return 0 ; 
64     }
65     else{
66         printf("0\n") ; 
67         ans = k ; 
68         for(int i=n;i>=1;i--) 
69         {
70             if( top[ i ]== m+1) continue ; 
71             for(int j=bot[ i ]+1;j<top[ i ];j++) 
72                 if(f[ i ][ j ]<inf) 
73                 {
74                     printf("%d\n",ans) ; 
75                     return 0 ; 
76                 }  
77             ans-- ; 
78         }
79         printf("0\n") ; 
80     }
81     return 0 ; 
82 }

 

posted @ 2017-07-08 12:32  third2333  阅读(165)  评论(0编辑  收藏  举报