HLOJ434 关灯

2人阅读 评论(0) 收藏 举报
分类:

题目

题目描述
宁智贤得到了一份有趣而高薪的工作。每天早晨她必须关掉她所在村庄的街灯。所有的街灯都被设置在一条直路的同一侧。 宁智贤每晚到早晨5点钟都在晚会上,然后她开始关灯。开始时,她站在某一盏路灯的旁边。 每盏灯都有一个给定功率的电灯泡,因为宁智贤有着自觉的节能意识,她希望在耗能总数最少的情况下将所有的灯关掉。 宁智贤因为太累了,所以只能以1m/s的速度行走。关灯不需要花费额外的时间,因为当她通过时就能将灯关掉。 编写程序,计算在给定路灯设置,灯泡功率以及宁智贤的起始位置的情况下关掉所有的灯需耗费的最小能量。
输入格式
第一行包含一个整数N,2≤N≤1000,表示该村庄路灯的数量。
第二行包含一个整数V,1≤V≤N,表示宁智贤开始关灯的路灯号码。
接下来的N行中,每行包含两个用空格隔开的整数D和W,用来描述每盏灯的参数,其中0≤D≤1000,0≤W≤1000。
D表示该路灯与村庄开始处的距离(用米为单位来表示),W表示灯泡的功率,即在每秒种该灯泡所消耗的能量数。路灯是按顺序给定的。
输出格式
第一行即唯一的一行应包含一个整数,即消耗能量之和的最小值。

题解

说实话,这道区间DP拿到手想了四十分钟一点思路都没有……看的题解才写出来的。。
这道题目要做的第一步是把所有的灯按照坐标进行排序
然后设出状态f[i][j]代表把第i盏灯到第j栈灯全部关闭的最小消耗。
但是问题出现了,我们发现对于一个区间[i,j],我们从i走到j的消耗和从j走到i的消耗是不一样的,所以我们新开一维,f[i][j][1]代表从左走到右边,f[i][j][0]代表从右走到左边。
对于f[i][j],我们只能从左边或者右边递推而来,也就是从f[i][j1]或者f[i1][j]推来。

code

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int num = 0;
    char c = ' ';
    bool flag = true;
    for(;c > '9' || c < '0';c = getchar())
    if(c == '-')
    flag = false;
    for(;c >= '0' && c <= '9';num = num*10+c-48,c=getchar());
    return flag ? num : -num;
}
const int maxn=1020;
int n,begining,P[maxn],sum[maxn][maxn];
//P是a[].power的前缀和
//sum[i][j]代表除去[i,j]的灯后的功率和 
struct light
{
    int direct,power;
}a[maxn];
bool mycmp(light a,light b)
{
    return a.direct<b.direct;
};
void init()
{
    n=read();
    begining=read();
    for(int i=1;i<=n;i++)
    {
        a[i].direct=read();
        a[i].power=read();
    }
    sort(a+1,a+1+n,mycmp);//排序 
    for(int i=1;i<=n;i++)
        P[i]=P[i-1]+a[i].power;//前缀和 
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            sum[i][j]=P[n]+P[i-1]-P[j];
}
int f[maxn][maxn][2];
void DP()
{
    memset(f,10,sizeof f);
    f[begining][begining][1]=f[begining][begining][0]=0;
    for(int len=2;len<=n;len++)
        for(int i=1;i+len-1<=n;i++)
        {
            int j=i+len-1;
            int t1,t2;
            t1=f[i+1][j][0]+(a[i+1].direct-a[i].direct)*sum[i+1][j];
            t2=f[i+1][j][1]+(a[j].direct-a[i].direct)*sum[i+1][j];
            f[i][j][0]=min(t1,t2);
            t1=f[i][j-1][0]+(a[j].direct-a[i].direct)*sum[i][j-1];
            t2=f[i][j-1][1]+(a[j].direct-a[j-1].direct)*sum[i][j-1];
            f[i][j][1]=min(t1,t2);
            //这部分画个图就能理解了 
        }
    printf("%d\n",min(f[1][n][0],f[1][n][1]));
}
int main()
{
    init();
    DP();
    return 0;
}
查看评论

简单的JavaScript实现开灯关灯效果 ↑_↑

近期做网页设计作业,感觉各种视频网站上的关灯效果很人性化,所以简易的用JavaScript写了一个   附上全部代码          无标题文档 #choose{  m...
  • NCITS
  • NCITS
  • 2012-05-05 20:49:38
  • 4418

【算法设计与分析基础】关灯游戏

Java实现关灯游戏的图形界面,附带关灯游戏算法分析ppt。可以输出所有结果。 如果不想要算法演示的话,请去掉File → Demo 的勾号。...
  • u013580497
  • u013580497
  • 2015-08-02 12:10:05
  • 4974

关灯游戏 Lights out (三)(线性代数+高斯消元,搜索全部解)

关灯游戏和线性代数联系紧密,对于一个 的灯阵,用线性方程组+高斯消元法求解,时间复杂度为O(m×n)^3。相对于首行枚举算法复杂度O(2^n) ,线代算法的时间复杂度低很多。用线性代数求解关灯游戏是个...
  • MHL_1208980380
  • MHL_1208980380
  • 2017-02-06 05:50:14
  • 2135

数学回味系列之4 - 开灯关灯问题

问题提出:        有编号1~100个灯泡,起初所有的灯都是灭的。有100个同学来按灯泡开关,如果灯是亮的,那么按过开关之后,灯会灭掉。如果灯是灭的,按过开关之后灯会亮。 现在开始按开关。   ...
  • linolzhang
  • linolzhang
  • 2017-02-21 23:08:32
  • 645

关灯游戏的算法Java实现

  • 2015年08月02日 11:59
  • 3.43MB
  • 下载

解决关灯游戏(Lights Off)

很多智力小游戏,背后都蕴藏着被码农们认为是“永远用不到”的课本知识。比如狡猾的”神经猫“,让女神妹子们娇嗔一句——好讨厌!而某些程序猿恍然大悟后,捋着屌丝,对小弟说:看,这就是Dijkstra算法。 ...
  • shuodai
  • shuodai
  • 2014-08-27 21:18:42
  • 1494

Js控制css——模仿视频网站关灯开灯

.day         {             background-color:White;         }                 .night         { ...
  • woshixuye
  • woshixuye
  • 2012-01-30 05:46:17
  • 2631

JS——开灯关灯

function turnon(){             document.getElementById("img").src="img/lightOn.jpg";              ...
  • niuyaotian
  • niuyaotian
  • 2016-07-21 14:36:25
  • 1014

纯CSS打造的图片开关灯效果

  • 2013年12月12日 19:24
  • 1KB
  • 下载

iOS关灯游戏AI的设计和实现

前段时间在一个美女的介绍下追了部美剧《疑犯追踪》(食我安利啦), 对人工智能好感度+max,于是花了两天时间在iOS上写了一个关灯游戏的AI,在这里拿出来分(zhuang)享(bi)。...
  • u013282174
  • u013282174
  • 2016-03-13 20:31:44
  • 1268
    博客专栏
    数论

    文章:16篇

    阅读:1734
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 1万+
    积分: 1453
    排名: 3万+
    友情链接!