zoukankan      html  css  js  c++  java
  • 【每日一题】27. 过河 (DP + 离散化)

    补题链接:Here

    算法涉及:DP + 离散化

    (l) 的范围太大,无法作为数组下标,所以先离散化,再DP。两点间的距离d大于t时,一定可以由 (d \% t) 跳过来,所以最多只需要t+d%t种距离的状态就可以表示这两个石子之间的任意距离关系。这样就把题目中的 (10^9) 压缩成了(2*t*m) 最多不超过 (2000) ,然后就可以放心大胆地用DP了。不过要注意题目中的“当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥”,所以DP的终点是一个范围而非确切的一个点,最后还要在这个范围内取最小值。

    using ll = long long;
    const int N = 1e6 + 10;
    const ll inf = 0x3f3f3f3f;
    ll dp[N], a[N], vis[N];
    void solve() {
    	int l, s, t, m;
    	cin >> l >> s >> t >> m;
    	for (int i = 1; i <= m; ++i)cin >> a[i];
    	sort(a + 1, a + 1 + m);
    	a[0] = 0, a[m + 1] = l;
    	int tmp = 0;
    	for (int i = 1; i <= m + 1; ++i) {
    		//这里一定要在取模后加t,否则会WA
    		if (a[i] - a[i - 1] > t)tmp += (a[i] - a[i - 1]) % t + t;
    		else tmp += a[i] - a[i - 1];
    		vis[tmp] = 1; //表示此处有石子
    	}
    	memset(dp, 0x3f, sizeof(dp));
    	dp[0] = 0;
    	for (int i = 1; i <= tmp + 100; ++i)
    		for (int j = s; j <= t; ++j)
    			if (i >= j)dp[i] = min(dp[i], dp[i - j] + vis[i]);
    	ll ans = inf;
    	//终点可能的范围,稍微写大点·
    	for (int i = tmp; i <= tmp + 100; ++i)
    		ans = min(ans, dp[i]);
    	cout << ans;
    }
    
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    最大上升子序列
    vue的keep-alive组件
    对小程序的研究3
    对getBoundingClientRect属性的研究
    消除浮动的方式
    对微信小程序的研究2
    对小程序的研究1
    对props的研究
    对provide/inject的研究
    对calc()的研究
  • 原文地址:https://www.cnblogs.com/RioTian/p/14773808.html
Copyright © 2011-2022 走看看