zoukankan      html  css  js  c++  java
  • Codeforces 1453F Even Harder

    题目链接

    点我跳转

    题目大意

    给定 (n) 个关卡 , 第 (i) 个关卡有个权值为 (ai) 的传送门

    当你在第 (i) 个关卡时 , 如果 (ai = 0) 并且 (i!=n) ,则你闯关失败

    否则你可以跳到 (i + 1) ~ (i + ai) 中的任意关卡 ( (ai + i <= n) )

    当你到达第 (n) 关时,闯关结束

    但为了增加闯关难度,系统要求你删除最少的传送门( 即令 (ai = 0) )

    使得从第一关开始,有且仅有一条可行的通关路线

    解题思路

    定义 (dp[i][x]) 为最小删除次数 , 使得从起点出发 , 只有一条可行路 , 这条可行路的终点为 (i)

    (i) 点的上一个点 (设为 (j)) 最远能到达的位置是 (x) (其中 (j + a[j] >= i))

    因为上一个点是 (j) , 且只有一条路

    那么对于 (k ∈[1,j-1]) , 如果 (k + a[k] >= i) ,需要把 (k) 删除

    对于 (k ∈[j + 1 , i - 1]) 如果 (k + a[k] >= i) ,需要把 (k) 删除

    (1) ~ (j-1) 需要删除的 (k) 的个数为 (pre) , (j+1) ~ (i-1) 需要删除的 (k) 的个数为 (suf)

    那么 $dp[i][j + a[j]] = pre + suf $

    对于 (suf) 可以从 (i - 1)(1) 枚举,每次碰到一个 (k + a[k] >= i,suf ++)

    对于 (pre) 它等于 (min( dp[j][i - 1] , dp[j][i - 2] ... dp[j][1]))

    其含义如下:

    最小删除次数

    使得从起点出发,有一条可行路 , 这条可行路的终点为 (j)

    (j) 点的上一个点 (k) 最远能到达的位置是 (i-1、i-2、i-3 ... 1) (即 (a[k] + k < i))

    对于 (pre) 的转移如果需要枚举 (i - 1 , i - 2 , ... , 1) 那么就多了一层循环 , (Tle) 警告

    而不难发现我们只需要找到最小的满足条件 (a[k] + k < i)(dp[j][x] , x ∈[1 , i - 1])

    所以我们可以维护一个前缀最小值 , 即 $dp[i][j] = min(dp[i][j] , dp[i][j - 1] $

    那么显然 (pre = dp[j][i - 1])

    最后答案为 (dp[n][n]) (从起点开始只有一条可行路线 , 路的终点为 (n) , (n) 的上一个点最远能达到的距离为 (n))

    AC_Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 3e3 + 10;
    int n , a[N] , dp[N][N];
    signed main()
    {
    	int T = 1;
    	cin >> T;
    	while(T --)
    	{
    		cin >> n;
    		for(int i = 1 ; i <= n ; i ++) cin >> a[i];
    		for(int i = 2 ; i <= n ; i ++) for(int j = 1 ; j <= n ; j ++) dp[i][j] = 2e9; //起点不能删除所以从 2 开始 
    		for(int i = 2 ; i <= n ; i ++)
    		{
    			int suf = 0;
    			for(int j = i - 1 ; j >= 1 ; j --)
    			{
    				if(j + a[j] >= i)
    				{
    					int pre = dp[j][i - 1];
    					dp[i][j + a[j]] = min(dp[i][j + a[j]] , pre + suf);
    					suf ++ ; 	
    				} 
    		 	}
    			for(int j = i ; j <= n ; j ++) dp[i][j] = min(dp[i][j] , dp[i][j - 1]);
    		}
    		cout << dp[n][n] << '
    ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    vue--路径前面的@的意思
    格式化规则修改prettierrc
    windows快捷键
    使用npm 添加less之后报错
    IOS中如何提高UITableView的性能?
    ffmpeg解码h264 Increasing reorder buffer
    Chrome浏览器关联文件图标空白问题解决方案
    mysql 问题sql 截图
    1、HR需要哪些自我提升
    1、文案职业大揭秘
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/14091911.html
Copyright © 2011-2022 走看看