zoukankan      html  css  js  c++  java
  • hdu 4842(NOIP 2005 过河)之 动态规划(距离压缩)

    /*
     
    hdu 4842(NOIP 2005 过河)之 动态规划(距离压缩)
     
    dp[i] := 到桥上的i位置,最少需要踩到的石子数。
     
    dp[i] = min(dp[i], dp[i-j] + isStone[i])   
    	条件:	(1) S<=j<=T
    		(2) dp[i-j]是青蛙可以到达的点
     
     
    独木桥长度L,最大为10^9,直接用转移方程,TLE;由于桥上的石子个数100,所以当石子分布在独木桥上时,是很稀疏的。
    (1)S!=T
        考虑,对于此题关键在于求踩到的石子数,而非跳的次数,对于两个相邻石子间的距离、起点与其相邻的最近石子间的距离、
        终点与其相邻的最近石子间的距离都可以进行压缩(整体可看成平移)。
        原因:
    		已知青蛙一次跳跃的最小距离S、以及最大距离T,当青蛙所在出发点与目标点的距离>=(T-1)*T时
    		(这个具体数值不精确,但是满足想达到的效果,下面有简单的证明),青蛙必然是可以到达目标点的。
    		这样,我们便可以利用这个来进行上面提及的距离压缩:将距离>=(T-1)*T的区间缩小(即平移),使青蛙
    		不再走那些一定可以到达的非石子点。
    (2) S==T
    	无法压缩(因为步长固定了),直接判断是否(stone_pos[i] % S == 0),若是,则踩到石子数+1;否则,无须处理。

    注意: 计算dp时,需要计算到dp[stone_pos[M + 1] + T - 1]。(因为有可能跳出stone_pos[M + 1])
        stone_pos[M + 1]为距离压缩后,独木桥终点。

    
    ------------------------------------------------------------------------------------------
    简单证明
    注:p可替换为青蛙一次跳跃的距离(T-1),p+1可替换为青蛙一次跳跃的距离(T),x、y即相应的距离跳了多少次。
      Q即为所有跳跃距离加起来的和。
     
    设:x*p + y*(p+1) = Q
    则:当Q>=p*(p+1)时,x,y一定有解
     
    证明:(来源于:ACdream群,[BNU]quailty)
    	(p+1)*p+0*(p+1)=p(p+1)
    	然后x--,y++
    			x		y		Q
    			(p)	       (1)		p(p+1) + 1
    			(p-1)	    (2)		p(p+1) + 2
    			......
    			(1)	       (p)		p(p+1) + p = p(p+2)
     
    	(p+2)*p+0*(p+1)=p(p+2)
    	然后x--,y++
    			x		y		Q
    			(p+1)	    (1)		p(p+2) + 1
    			(p)	        (2)		p(p+2) + 2
    			......
    			(2)		(p)		p(p+2) + p = p(p+3)
    	......
    	以此类推,可以到达距离起点>=p*(p+1)的任一点。
    	(虽然不严格,但是有助于理解)。
    ------------------------------------------------------------------------------------------
     
    */
      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cstddef>
      7 #include <iterator>
      8 #include <algorithm>
      9 #include <string>
     10 #include <locale>
     11 #include <cmath>
     12 #include <vector>
     13 #include <cstring>
     14 #include <map>
     15 #include <utility>
     16 #include <queue>
     17 #include <stack>
     18 #include <set>
     19 #include <functional>
     20 using namespace std;
     21 typedef pair<int, int> PII;
     22 typedef long long int64;
     23 const int INF = 0x3f3f3f3f;
     24 const int modPrime = 3046721;
     25 const double eps = 1e-9;
     26 const int MaxN = 11000;
     27 const int MaxM = 110;
     28 const char Opt[4] = { '+', '-', '*', '/' };
     29 
     30 int stone_pos[MaxM];
     31 int dp[MaxN];
     32 int isStone[MaxN];
     33 int L, S, T, M;
     34 
     35 int Solve()
     36 {
     37     int rel = 0;
     38     if (S == T)
     39     {
     40         for (int i = 1; i <= M; ++i)
     41         {
     42             if (stone_pos[i] % S == 0)
     43             {
     44                 ++rel;
     45             }
     46         }
     47     }
     48     else
     49     {
     50         int disLen = (T-1)*T;
     51         stone_pos[0] = 0;
     52         stone_pos[M + 1] = L;
     53         sort(stone_pos + 1, stone_pos + M + 1);
     54         int moveLen = 0;
     55         for (int i = 1; i <= (M + 1); ++i)
     56         {
     57             int dis = stone_pos[i] - stone_pos[i - 1] - moveLen;
     58             if (dis > disLen)
     59             {
     60                 moveLen += (dis - disLen);
     61             }
     62             stone_pos[i] -= moveLen;
     63 
     64             if (i != (M + 1))
     65             {
     66                 isStone[stone_pos[i]] = 1;
     67             }
     68         }
     69         dp[0] = 0;
     70         for (int i = S; i <= stone_pos[M + 1] + T - 1; ++i)
     71         {
     72             for (int j = i - T; j <= i - S; ++j)
     73             {
     74                 if ((j >= 0) && (-1 != dp[j]))
     75                 {
     76                     if (-1 == dp[i])
     77                     {
     78                         dp[i] = dp[j] + isStone[i];
     79                     }
     80                     else
     81                     {
     82                         dp[i] = min(dp[i], dp[j] + isStone[i]);
     83                     }
     84                 }
     85             }
     86         }
     87 
     88         rel = INF;
     89         for (int i = stone_pos[M + 1]; i <= stone_pos[M + 1] + T - 1; ++i)
     90         {
     91             if (-1 != dp[i])
     92             {
     93                 rel = min(rel, dp[i]);
     94             }
     95         }
     96     }
     97     return rel;
     98 }
     99 
    100 int main()
    101 {
    102 #ifdef HOME
    103     freopen("in", "r", stdin);
    104     //freopen("out", "w", stdout);
    105 #endif
    106 
    107     int caseNum = 0;
    108     while (~scanf("%d", &L))
    109     {
    110         if (caseNum != 0)
    111         {
    112             cout << endl;
    113         }
    114         fill(stone_pos, stone_pos + MaxM, 0);
    115         fill(dp, dp + MaxN, -1);
    116         fill(isStone, isStone + MaxN, 0);
    117         scanf("%d %d %d", &S, &T, &M);
    118         for (int i = 1; i <= M; ++i)
    119         {
    120             scanf("%d", &stone_pos[i]);
    121         }
    122         int rel = Solve();
    123         cout << rel;
    124         ++caseNum;
    125     }
    126     
    127 
    128 #ifdef HOME
    129     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
    130     _CrtDumpMemoryLeaks();
    131 #endif
    132     return 0;
    133 }
    
    
    
     
  • 相关阅读:
    InfluxDB执行语句管理(query management)
    InfluxDB数据备份和恢复方法,支持本地和远程备份
    WordPress多本小说主题–WNovel主题发布,十分钟搭建小说站! 现已更新至1.2版本
    InfluxDB安装后web页面无法访问的解决方案
    Influxdb原理详解
    InfluxDB学习之InfluxDB连续查询(Continuous Queries)
    InfluxDB学习之InfluxDB数据保留策略(Retention Policies)
    InfluxDB学习之InfluxDB的HTTP API查询操作
    玩游戏,王者荣耀,记录
    开源抓包工具PowerSniff(支持lua,c语言作为脚本实时分析)
  • 原文地址:https://www.cnblogs.com/shijianming/p/5149559.html
Copyright © 2011-2022 走看看