九度OJ 1086

链接:
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;
}
发布了56 篇原创文章 · 获赞 49 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/IBelieve2016/article/details/77782747