zoukankan      html  css  js  c++  java
  • 【bzoj3379】[Usaco2004 Open]Turning in Homework 交作业 区间dp

    题目描述

    数轴上有C个点,每个点有一个坐标和一个访问时间,必须在这个时间后到达这个点才算访问完成。可以在某个位置停留。每在数轴上走一个单位长度消耗一个单位的时间,问:访问所有点并最终到B花费的最小时间。

    输入

    第1行输入三个整数C,H,B,B是出口的位置.之后C行每行输入两个整数,分别表示一个老师所在的教室和他的下课时间.

    输出

    贝茜最早能够到达出口的时间.

    样例输入

    4 10 3
    8 9
    4 21
    3 16
    8 12

    样例输出

    22


    题解

    区间dp

    考试题。。。考挂了。。。

    (以下内容复制自题解)

    考虑 dp[i][j][0/1]表示已经处理了从左数的 i 个和从右数的 j 个的案件,当前在 i 还是在 j
    dp[i][j][0]可以由 dp[i-1][j][0],dp[i][j+1][1]+dis 来转移
    dp[i][j][1]同理。

    (以上内容复制自题解)

    个人想法:

    首先一定是先处理区间端点。一个大概思路是:对于非必选的点能不选就不选,而区间端点必选,其余点不必选,因此只需要考虑区间端点。

    (或者一个更好的思考方法是:考虑把这个过程反过来,变为从$B$开始走,每个点必须在$ANS-T_i$时间内到达,最终要求到达0位置。显然经过的点一定不会傻到不选,因此反过程先选中间再选端点,正过程就是先选端点再选中间。
    PS:$ANS$满足单调性,因此CQzhangyu就这样切了此题。。)

    然后设$f[i][j][0/1]$表示左端点为$i$,右端点为$j$,当前处理完$i/j$的最小时间。直接转移即可。注意一下这是一个半开半闭区间的状态,因此初始状态需要计算,最终答案直接用$f[i][i][0/1]$统计。

    时间复杂度$O(n^2)$

    代码简单的不行= =

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 1010
    using namespace std;
    struct data
    {
    	int p , t;
    	bool operator<(const data &a)const {return p < a.p;}
    }a[N];
    int f[N][N][2];
    int main()
    {
    	int n , m , i , j , k , ans = 1 << 30;
    	scanf("%d%*d%d" , &n , &m);
    	for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i].p , &a[i].t);
    	sort(a + 1 , a + n + 1);
    	memset(f , 0x3f , sizeof(f));
    	f[1][n][0] = max(a[1].p , a[1].t) , f[1][n][1] = max(a[n].p , a[n].t);
    	for(k = n - 1 ; k ; k -- )
    	{
    		for(i = 1 ; i <= n - k + 1 ; i ++ )
    		{
    			j = i + k - 1;
    			if(i > 1) f[i][j][0] = min(f[i][j][0] , f[i - 1][j][0] + a[i].p - a[i - 1].p) , f[i][j][1] = min(f[i][j][1] , f[i - 1][j][0] + a[j].p - a[i - 1].p);
    			if(j < n) f[i][j][0] = min(f[i][j][0] , f[i][j + 1][1] + a[j + 1].p - a[i].p) , f[i][j][1] = min(f[i][j][1] , f[i][j + 1][1] + a[j + 1].p - a[j].p);
    			f[i][j][0] = max(f[i][j][0] , a[i].t) , f[i][j][1] = max(f[i][j][1] , a[j].t);
    		}
    	}
    	for(i = 1 ; i <= n ; i ++ ) ans = min(ans , min(f[i][i][0] , f[i][i][1]) + abs(a[i].p - m));
    	printf("%d
    " , ans);
    	return 0;
    }
    
  • 相关阅读:
    如何紧急恢复SQL Server主数据库
    合理利用SQL Server查询执行计划
    理解RAID的四种级别
    sp_spaceused 显示行数、保留的磁盘空间以及当前数据库中的表、索引视图
    修复数据库索引问题:理解填充因数设置
    SQL Server调整因子
    sqlservr 命令行启动
    DBA需要考虑备份相关问题
    BCP
    “tablediff ”命令行工具
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7724163.html
Copyright © 2011-2022 走看看