链接:
http://ac.jobdu.com/problem.php?pid=1086
http://ac.jobdu.com/oldexamset.php
清华2011机试题
1086
题目描述:
在某条线路上有N个火车站,有三种距离的路程,L1,L2,L3,对应的价格为C1,C2,C3.其对应关系如下:
距离s 票价
0 < S<=L1 C1
L1 < S<=L2 C2
L2 < S<=L3 C3
输入保证0 < L1 < L2 < L3 < 10^9,0 < C1 < C2 < C3 < 10^9。
每两个站之间的距离不超过L3。
当乘客要移动的两个站的距离大于L3的时候,可以选择从中间一个站下车,然后买票再上车,所以乘客整个过程中至少会买两张票。
现在给你一个 L1,L2,L3,C1,C2,C3。然后是A B的值,其分别为乘客旅程的起始站和终点站。
然后输入N,N为该线路上的总的火车站数目,然后输入N-1个整数,分别代表从该线路上的第一个站,到第2个站,第3个站,……,第N个站的距离。
根据输入,输出乘客从A到B站的最小花费。
思路:
很简单的动态规划题,很容易想到,就是对a到b的每个站,都计算一下最小花费。需要注意的是数据范围,我被数据范围困了好久。
除了a, b, num,其他所有的都改成long long之后,AC了
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include "stdio.h"
using namespace std;
long long dis[100000];
long long dp[100000];
int main(){
long long l1, l2, l3, c1, c2, c3;
int n;
int a, b;
while (scanf("%Ild%Ild%Ild%Ild%Ild%Ild", &l1, &l2, &l3, &c1, &c2, &c3) != EOF){
scanf("%d%d", &a, &b);
scanf("%d", &n);
memset(dis, 0, sizeof(dis));
memset(dp, 0x7f, sizeof(dp));
for (int i = 2; i <= n; i++){
scanf("%lld", &dis[i]);
}
if (a > b){ int swapp = a; a = b; b = swapp; }
dp[a] = 0;
for (int i = a + 1; i <= b; i++){
int temp = i - 1;
while (temp >= a && dis[i] - dis[temp] <= l3){
if (dis[i] - dis[temp] <= l1) dp[i] = min(dp[i], dp[temp] + c1);
else if (dis[i] - dis[temp] <= l2) dp[i] = min(dp[i], dp[temp] + c2);
else dp[i] = min(dp[i], dp[temp] + c3);
temp--;
}
//cout << "dp[" << i << "] = " << dp[i] << endl;
}
printf("%lld\n", dp[b]);
}
return 0;
}
1087 约数的个数
题目描述:
输入n个整数,依次输出每个数的约数的个数
很简单,虽然数据范围比较大,但是用sqrt就很快了。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int main(){
int n;
long long num;
while (true){
scanf("%d", &n);
if (n == 0) break;
for (int i = 0; i < n; i++){
int ans = 0;
scanf("%I64d", &num);
double sk = sqrt(num * 1.0);
int sk2 = sqrt(num);
if (num == 1) {
printf("1\n"); continue;
}
for (int j = 1; j < sk; j++){
if (num % j == 0) ans = ans + 2;
}
if (sk == sk2) ans++;
printf("%d\n", ans);
}
}
return 0;
}
1088 剩下的树
题目描述:
有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,...,L共L+1个位置上有L+1棵树。
现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。
可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。
很简单,直接用一个数组表示每个位置是否有树,每个区间都去修改这个数组即可。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int ans[10005];
int main(){
int l, m;
while (scanf("%d%d", &l, &m) != EOF){
int num = 0;
memset(ans, 0, sizeof(ans));
for (int i = 1; i <= m; i++){
int x, y;
scanf("%d%d", &x, &y);
for (int j = x; j <= y; j++){
ans[j] = 1;
}
}
for (int i = 0; i <= l; i++){
if (ans[i] == 0) num++;
}
printf("%d\n", num);
}
return 0;
}