火车票(ticket.cpp Time:0.1s Memory:512M)
问题描述
一个铁路线上有 n(2<=n<=10000)个火车站,每个火车站到该线路的首发火车站距离都是已知的。任意两站之间的票价如下表所示:站之间的距离 – X 票价
0< X <= L1 C1
L1 < X <= L2 C2
L2 < X <= L3 C3
其中 L1,L2,L3,C1,C2,C3 都是已知的正整数,且(1 <= L1 < L2 < L3 <= 10^9, 1 <=C1 < C2 < C3 <= 10^9)。显然若两站之间的距离大于 L3,那么从一站到另一站至少要买两张票。
注意:每一张票在使用时只能从一站开始到另一站结束。
对于给定的线路,求出从该线路上的站 A 到站 B 的最少票价。
输入
输入文件的第一行为 6 个整数, L1 , L2 , L3 , C1 , C2 , C3 (1 <= L 1 < L 2 < L 3 <= 10^9, 1<= C 1 < C 2 < C 3 <= 10^9) ,这些整数由空格隔开.第二行为火车站的数量 N (2 <= N <= 10000).第三行为两个不同的整数 A、B,由空格隔开。接下来的 N -1 行包含从第一站到其他站之间的距离.这些距离按照增长的顺序被设置为不同的正整数。相邻两站之间的距离不超过 L 3 .两个给定火车站之间行程花费的最小值不超过 10^9,而且任意两站之间距离不超过 10^9。
输出
输出文件中只有一个数字,表示从 A 到 B 要花费的最小值.
输入样例
3 6 8 20 30 40
7
2 6
3
7
8
13
15
23
输出样例
70
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int sm = 1e4+5;
int l1,l2,l3,c1,c2,c3;
int n,a,b,s[sm],f[sm];
bool get(int x,int y) {
return s[y]-s[x]<=l3;
}
int dis(int x,int y) {
int dt=s[y]-s[x];
if(dt<=l1)return c1;
if(dt<=l2)return c2;
if(dt<=l3)return c3;
}
int main() {
freopen("ticket.in","r",stdin);
freopen("ticket.out","w",stdout);
memset(f,0x7f,sizeof(f));
scanf("%d%d%d%d%d%d",&l1,&l2,&l3,&c1,&c2,&c3);
scanf("%d%d%d",&n,&a,&b);
if(a>b)swap(a,b);f[a]=0;
for(int i=2;i<=n;++i)scanf("%d",&s[i]);
for(int i=a+1;i<=b;++i)
for(int j=i-1;j>=a&&get(j,i);--j)
f[i]=min(f[i],f[j]+dis(j,i));
printf("%d\n",f[b]);
return 0;
}
艺术馆的火灾 (fire.cpp Time:1s Memory:512M)
问题描述
这幢古老的建筑是一个艺术馆,它珍藏着上百件绘画、雕塑以及其他艺术品,就连建筑本身也是一件艺术。但是,岁月并不在乎它的精致与美丽,时光在渐渐剥夺着这幢木屋的生命。终于,在一个月色昏暗的夜晚,它着火了。艺术馆是一幢两层的小楼,每一层有 N 个房间,每个房间中收藏的艺术品的价值都可以用一个正整数来表示。下面是一个 N=4 的例子。
屋顶 | 屋顶 | 屋顶 | 屋顶 |
---|---|---|---|
40 | 50 | 30 | 60 |
30 | 30 | 40 | 20 |
在这个例子中,二层楼的第四个房间中艺术品的价值最大,为 60。而一层楼的第四个房间中艺术品的价值仅为 20。在消防队员火速赶到的时候,火势已经蔓延了整个建筑,消防队员们观察每个房间中的火势,将它们分别用一个正整数来表示。在上面的例子中,各房间中的火势可能如下。
屋顶 | 屋顶 | 屋顶 | 屋顶 |
---|---|---|---|
50 | 40 | 50 | 70 |
40 | 50 | 20 | 30 |
你可以看到,二层楼的第四个房间中火势最强,为 70。而一层楼的第三个房间中火势较弱,为 20。由于火情紧急,消防队员们准备使用一种新型的灭火器。这种灭火器只能发射 K 次,每次发射将覆盖一个矩形的区域(矩形的高度可以是 1 也可以是 2)。它的威力巨大,所到之处不但火焰会被扑灭,就连同在一处的艺术品也难以幸免。因此,如何善用这种灭火器成了最大的问题。
任务说明
给出艺术馆每层的房间数 N 和灭火器的发射次数 K,以及每个房间中艺术品的价值和火势,你需要决定灭火器每次应该怎样发射(也可以不发射),才能将这次火灾的损失降到最低限度。这个损失用你所摧毁的艺术品的总价值,加上剩余的火势总值(这些火焰将需要消防队员们亲身去扑灭)来衡量。
输入
输入文件的第一行有两个整数N(1 <= N <= 100)、K(1 <= K <= 10),分别表示艺术馆中每层的房间数和灭火器的发射次数。
接下来的两行每行有N个整数,其中第4-i行的第j个整数Vi,j表示的是第i层第j个房间中艺术品的价值(1<= i <= 2,1 <=j<=N,1 <=Vi,j <= 10000)。
再接下来的两行每行也有N个整数,其中第6-i行的第j个整数Fi,j表示的是第i层第j个房间中的火势(1 <= i <= 2,1 <= j <= N,1 <= Fi,j <= 10000)。
输出
你的输出文件应该有K行,每行有四个整数L1、R1、L2、R2,表示你的灭火器的一次行动。如果灭火器这次不发射,那么这四个整数都为0;否则这次发射所覆盖的矩形区域的左下角是第L1层的第R1个房间,右上角是第L2层的第R2个房间。
注意:你的每次发射所覆盖的矩形区域必须位于小楼之内,并且矩形的面积至少为0。即1 <= L1 <= L2 <=2,1<= R1 <= R2 <= N。
输入输出样例
INPUT.TXT
4 2
40 50 30 60
30 30 40 20
50 40 50 70
40 50 20 30
OUTPUT.TXT
1 1 1 2
2 3 2 4
摧毁艺术品:30+60+30+30=150
剩余火势:50+40+20+30=140
最小损失:150+140=290
分析
首先将问题转化成模型:在一个 2×N 的矩阵中,找出 K 个子矩阵。我们将这些子矩阵所包含的元素集合用 S 来表示的话,那么问题的目标就是使下式最小