zoukankan      html  css  js  c++  java
  • 【NOIP2014】飞扬的小鸟

      题目戳这里

      70分是很裸的。

      定义f[i][j]表示到了(i,j)位置最少戳的次数

      有三种转移

      ●f[i][j]=min{f[i-1][j-k*x[i-1]]+k}--------------------------dp1

      从(i,j-k*x)连戳k次跳到(i,j)

      ●f[i][j]=min(f[i][j],f[i-1][j+y[i-1]])-------------------------dp2

      从(i,j+y)不戳掉到(i,j)

      ●if(j==m)f[i][j]=min(f[i][j],f[i-1][t]+(j-t)/x[i-1]+1) -----dp3 

      t为 i-1处的任意合法位置

      j在顶端,所以只要(i-1,t)合法可能从任意 t 跳到(i,j),因为碰到上界无法跳且不死

      

      复杂度O(NM^2) 一个稳稳的T

      100分有一个小优化

      这样思考:此题是可以过O(NM)的,而f[i][j]是必须要的,i和j必须枚举,那么我们k的枚举就必须被干掉。   

      

      

                         

      假设1,2,3,4,5,6,7,8号点和(i,j)点均合法

      可见,对于上图

    (i,j)点要由1,2,3,4号点转移过来

      而5号点由2,3,4号点转移过来------->(i,j)可由5号点和1号点转移

         6号点由3,4号点转移过来------->5号点可由6号点和2号点转移

             7号点由4号点转移过来------->6号点可由7号点和3号点转移

      f[i][j]可由f[i-1][j-x[i-1]]和f[i][j-x[i-1]]转移

      道理很显然

      f[i-1][j-k*x[i-1]]+k(k>=2)的信息全部存到了f[i][j-x[i-1]]中,k只用枚举1就行了

      由于其他转移均为O(1),所以不用优化

      复杂度O(NM)  

      另外,若不能到达n,要求出能通过几根管子

      这个其实很简单,只某一横坐标上所有合法点值均为inf,那么肯定不能到达此位置

      记录个最远到达的横坐标,判断此横坐标前有几根管子就行了

      写代码时有几点要注意

      ●先把所有向上跳的转移后再来转移向下降的

      为什么?    因为我们毕竟不是(i,j-x[i-1])点跳上来的

      如果(i,j-x[i-1])点最优转移是向下降,且(i,j)点最优转移是f[i][j-x[i-1]]

      那么我们的f[i][j]=f[i][j-x[i-1]]是什么意思?先向下落了一点又跳上来?

      这不符合游戏规则,所以要分开写。

        ●不只转移合法点,非法点(管子)也必须转移,因为它会存有(i-1,j-k*x[i-1])k>=2的信息

      ●判断来源点是否合法

      

       

      至此,此题已解决

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #define ll long long
    #define N 1005
    using namespace std;
    int up[N*10],dn[N*10],x[N*10],y[N*10],f[N*10][N],n,m,k,ans2,ans1=0x3f3f3f3f;
    int main(){
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]);
    	for(int i=0;i<=n;i++)up[i]=m+1,dn[i]=0;
    	for(int i=1;i<=k;i++){
    		int p;scanf("%d",&p);
    		scanf("%d%d",&dn[p],&up[p]);
    	}
    	memset(f,0x3f,sizeof(f));
    	for(int i=0;i<=m;i++)f[0][i]=0;
    	for(int i=1;i<=n;i++){
    		int fg=0;
    		for(int j=1;j<=m;j++){
    			if(j-x[i-1]>0)f[i][j]=f[i][j-x[i-1]]+1;
    			if(j-x[i-1]>dn[i-1]&&j-x[i-1]<up[i-1])      //dp1
    			f[i][j]=min(f[i][j],f[i-1][j-x[i-1]]+1);
    			if(j==m)for(int t=1;t<=j;t++)               //dp2
    			if(t>dn[i-1]&&t<up[i-1])f[i][j]=min(f[i][j],f[i-1][t]+(j-t)/x[i-1]+1);
    		}
    		for(int j=dn[i]+1;j<up[i];j++){
    			if(j+y[i-1]>dn[i-1]&&j+y[i-1]<up[i-1])      
    			f[i][j]=min(f[i][j],f[i-1][j+y[i-1]]);
    			if(f[i][j]<0x3f3f3f3f)fg=1;
    		}
    		if(fg)ans2=i;
    		else break;
    	}
    	if(ans2!=n){
    		int cnt=0;
    		for(int i=0;i<=ans2;i++)if(up[i]!=m+1)cnt++;
    		printf("0
    %d",cnt);
    	}
    	else{
    		for(int i=dn[n]+1;i<up[n];i++)ans1=min(ans1,f[n][i]);
    		printf("1
    %d",ans1);
    	}
    	return 0;
    }
    

      

      

  • 相关阅读:
    np.newaxis
    UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 576-577: invalid continuation byte
    shell $() vs ${}
    install docker-ce for ubuntu
    ImportError: pycurl: libcurl link-time ssl backend (nss) is different
    saltstack install on centos7
    pycharm 用远程环境时报错bash: line 0: cd: /home/tmp: No such file or directory
    计算函用运行用时
    scrapy-redis
    merge dict key
  • 原文地址:https://www.cnblogs.com/wsy01/p/7545517.html
Copyright © 2011-2022 走看看