• LRJ入门经典0907万圣节的小L306


    原题

    LRJ入门经典-0907万圣节的小L306
    难度级别:B; 运行时间限制:1000ms; 运行空间限制:256000KB; 代码长度限制:2000000B
    试题描述

    今天是万圣节,小L同学开始了一年一度的讨要糖果游戏,但是在刚刚过去的比赛中小有成就的他打算给自己增加一点难度:如果没有讨到每一家的糖果就算输。

    已知小L共有n(n不大于10000)个邻居,他们都在同一条街上(可以近似看成一条直线),第i个邻居的坐标是xi。L同学的妈妈会在一开始把他送到任意邻居的门前。现在已知所有邻居会在di时间后休息(休息以后不能再去打扰),求访问完所有点的最短时间,如果无解输出“No solution”。

    输入
    输入第一行为一个正整数表示n,接下来n行,每行两个用空格隔开的数,分别表示第i个邻居的位置和休息时间。
    输出
    输出一个数,表示最短时间,无解输出“No solution”。
    输入示例
    5
    1 3
    3 1
    5 8
    8 19
    10 15
    输出示例
    11

    分析1

    当一看到“(n不大于10000)”时,就大约知道这是一道动态规划了。

    再一看到“(可以近似看成一条直线)”时,就大概知道这是一道区间DP

    一切的一切都在说明一件事:读题很重要(语文很重要)

    状态:

    dp[i][j][0]:将第i~j户邻居的糖果在他们休息之前全部要到,并在最后停在左边的最短时间。
    dp[i][j][1]:将第i~j户邻居的糖果在他们休息之前全部要到,并在最后停在的最短时间。

    转移方程:

    这个可能有点难:

    x=dp[i][j-1][1]+a[j]-a[j-1];

    y=dp[i][j-1][0]+a[j]-a[i];

    if(x>b[j]) x=INF;

    if(y>b[j]) y=INF;

    dp[i][j][1]=min(dp[i][j][1],min(x,y));

     

    x=dp[i][j-1][0]+a[j]-a[j-1];

    y=dp[i][j-1][1]+a[j]-a[i];

    if(x>b[j]) x=INF;

    if(y>b[j]) y=INF;

    dp[i][j][0]=min(dp[i][j][0],min(x,y));

    答案:

    很显然是min(dp[1][n][0],dp[1][n][1])。

    代码1

    先上一段错误的代码:

    分析2

    显然上段代码的dp数组开不下了!

    不要慌!

    冷静思考!

    首先想解决办法:

    1、(谁都能想到)压缩数组

    2、(这个有点儿难)用滚动数组

    将dp[i][j][k]的i压缩成2

    直接上代码!

    代码2

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define INF 1073741824
    using namespace std;
    int dp[2][10001][2],n;
    int a[10001],b[10001];
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
    	for(int i=1;i<=n;i++) dp[0][i][0]=dp[1][i][1]=0;
    	for(int k=1;k<n;k++)
    	{
    		for(int i=1;i+k<=n;i++)
    		{
    			int j=i+k,x,y;
    			int I=(i%2)^1;
    			dp[i%2][j][0]=dp[i%2][j][1]=INF;
    			x=dp[i%2][j-1][1]+a[j]-a[j-1];y=dp[i%2][j-1][0]+a[j]-a[i];
    			if(x>b[j]) x=INF;
    			if(y>b[j]) y=INF;
    			dp[i%2][j][1]=min(dp[i%2][j][1],min(x,y));
    			//cout<<"i:"<<i<<"  j:"<<j<<"  o:1"<<"  x:"<<x<<"  y:"<<y<<"  dp:"<<dp[i%2][j][1]<<endl;
    			x=dp[I][j][0]+a[i+1]-a[i];y=dp[I][j][1]+a[j]-a[i];
    			if(x>b[i]) x=INF;
    			if(y>b[i]) y=INF;
    			dp[i%2][j][0]=min(dp[i%2][j][0],min(x,y));
    			//cout<<"i:"<<i<<"  j:"<<j<<"  o:0"<<"  x:"<<x<<"  y:"<<y<<"  dp:"<<dp[i%2][j][0]<<endl<<endl;
    		}
    	}
    	if(min(dp[1][n][0],dp[1][n][1])==INF) cout<<"No solution";
    	else cout<<min(dp[1][n][0],dp[1][n][1]);
    	return 0;
    }
    

      

  • 相关阅读:
    Centos 卸载openjdk
    Hadoop安装之Hive集成与mysql安装
    Hadoop安装-Spark Windows 环境 pycharm开发环境搭建
    Hadoop安装—Spark安装
    Hadoop安装-伪分布式
    Hadoop安装之JDK在Centos虚拟机中安装
    SQL server 数据库调用远程数据库存储过程的实现方法
    以梦为马,铸就美好人生
    kettle实战演练——批量解压有密码的rar文件,并生成xml文件
    Linux diff命令
  • 原文地址:https://www.cnblogs.com/chenjiaxuan/p/10180745.html
Copyright © 2020-2023  润新知