zoukankan      html  css  js  c++  java
  • luogu1941 [NOIp2014]飞扬的小鸟 (dp)

    设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
    ",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
    ",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
    ",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
    ",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
    ",ans);
    69     }else{
    70         printf("%d
    ",cnt);
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    C++中使用多线程
    hdu 4223 dp 求连续子序列的和的绝对值最小值
    hdu 1372 bfs 计算起点到终点的距离
    hdu 4217 线段树 依次取第几个最小值,求其sum
    心得
    hdu 1175 bfs 按要求进行搜索,是否能到达,抵消两个(相同)棋子
    hdu 4221 greed 注意范围 工作延期,使整个工作时间罚时最少的单个罚时最长的值
    hdu 2844 多重背包 多种硬币,每一种硬币有一点数量,看他能组成多少种钱
    uva LCDDisplay
    hdu 4218 模拟 根据一个圆点和半径画一个圆 注意半径要求
  • 原文地址:https://www.cnblogs.com/Ressed/p/9703780.html
Copyright © 2011-2022 走看看