zoukankan      html  css  js  c++  java
  • LGOJP1941 飞扬的小鸟

    题目链接

    题目链接

    题解

    (f[i][j])表示位置((i,j))到达需要的最小点击数。
    (f[i][j]=min{{f[i-1][j-kx]+k},f[i-1][j+y]})
    (O(nm^2))
    考虑优化,首先(f)可以滚动,然后考虑优化掉一个(m)
    (g[j])表示((i-1,j))往下每(x_i)个单位的(min)。显然有(g[j]=min{f[i][j],g[j-x_{i}]+1})
    那么则有(f[i][j]=min{g[j-x_i]+1,f[i-1][j+y]})。复杂度(O(nm))
    有个需要注意的点是到了跳到m就不能再高了,所以对于({(i,j)|j+x_i>m})的点没办法利用g(O(1))转移(共有m-j个合法可转移点),这个可以通过对g维护一个后缀(min)解决。
    好像也可以类比01背包和完全背包来转移。不过我想的时候没想到那个方向QAQ。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int inf = 0x3f3f3f3f;
    const int N = 10010;
    int n, m, k, f[2][1010], g[1010], x[N], y[N];
    int p[N][2];
    
    int main() {
    	scanf("%d%d%d", &n, &m, &k);
    	for(int i = 0; i < n; ++i) 
    		scanf("%d%d", &x[i], &y[i]), p[i][0] = 0, p[i][1] = m + 1;
    	p[n][0] = 0; p[n][1] = m + 1;
    	for(int i = 1; i <= k; ++i) {
    		int px, l, h;
    		scanf("%d%d%d", &px, &l, &h);
    		p[px][0] = l; p[px][1] = h;
    	}
    	int cur = 0, to = 0, min_val = inf;
    	for(int i = 1; i <= n; ++i) {
    		cur ^= 1;
    		for(int j = 1; j <= m; ++j) f[cur][j] = inf; 
    		
    		for(int j = 1; j <= m; ++j) {
    			if(j <= p[i][0] || j >= p[i][1]) continue;
    			
    			if(j == m) f[cur][j] = min(f[cur][j], min_val + 1); 
    			if(j - x[i - 1] > 0 && j - x[i - 1] > p[i - 1][0]) 
    				f[cur][j] = min(f[cur][j], g[j - x[i - 1]] + 1);
    			if(j + y[i - 1] <= m && j + y[i - 1] < p[i - 1][1]) 
    				f[cur][j] = min(f[cur][j], f[cur ^ 1][j + y[i - 1]]);
    			
    			if(f[cur][j] != inf) to = i;
    		}
    
    		for(int j = 1; j <= m; ++j) g[j] = inf; 
    		min_val = inf;
    		for(int j = 1; j <= m; ++j) {
    			g[j] = f[cur][j];
    			if(j - x[i] > 0) g[j] = min(g[j], g[j - x[i]] + 1);
    			if(j + x[i] >= m) 
    				min_val = min(min_val, g[j]);
    		}
    	}
    	if(to == n) {
    		int ans = inf;
    		for(int j = 1; j <= m; ++j) ans = min(ans, f[cur][j]);
    		printf("1
    %d
    ", ans);
    	} else {
    		int tot = 0;
    		for(int i = 0; i <= to; ++i) {
    			if(!(p[i][0] == 0 && p[i][1] == m + 1)) ++tot;
    		}
    		printf("0
    %d
    ", tot);
    	}
    	return 0;
    }
    
  • 相关阅读:
    二、java基本语法
    LINQ入门教程之各种标准查询操作符(一)
    LINQ入门教程之各种标准查询操作符(二)
    读《穷爸爸 富爸爸》有想
    考考你的逻辑推理能力
    读《自控力》有感
    读大数据有感
    django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.的解决办法
    RabbitMQ入门
    ubuntu安装mysql可视化工具MySQL-workbench及简单操作
  • 原文地址:https://www.cnblogs.com/henry-1202/p/11316065.html
Copyright © 2011-2022 走看看