• 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)


    G. Car Repair Shop

    题目链接:http://codeforces.com/contest/730/problem/G

    题意:

      修车店提前问好n位顾客想要送车的时间Si和修车辆车的时间Ki,然后修车店安排时间,对于第i辆车如果【Si,Si+Ki-1】这段时间是有空的修车,如果没空则找到第一天满足【Ti,Ti+Ki-1】这段时间有空,安排修车,注意Ti可以<Si。输出每辆车修车的时间。

    input
    3
    9 2
    7 3
    2 4
    output
    9 10
    1 3
    4 7
    input
    4
    1000000000 1000000
    1000000000 1000000
    100000000 1000000
    1000000000 1000000
    output
    1000000000 1000999999
    1 1000000
    100000000 100999999
    1000001 2000000

    分析:
      在比赛想复杂了,结果错了。正确的思维使用数组l和数组r维护1-n辆车对用的修车时间。输入的起始时间为x,持续时间为y。l[0]和r[0]都置为0.l[0]和r[0]用在当前时间如果已经安排了修车的话,从l[0]+1时刻开始找合适的时间安排
      对于来修的车,如果他与之前的没有冲突,直接用这段时间修车,即l[i]=x,r[i]=x+y-1。如果有冲突,让l[i]=r[j]+1,r[i]=l[i]+y-1;判断这段时间与之前的时候有冲突,没冲突就选这段时间。j从0-i循环。
    代码:
      
    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 1111;
    int l[MAXN], r[MAXN], n, cnt;
    //用于检验当前时间是否与之前安排好的时间冲突,没冲突返回true
    inline bool check(int x, int y) {
        for (int i = 1; i <= cnt; ++i)
            if (!(x > r[i] || y < l[i])) return false;
        return true;
    }
    
    int main() {
        scanf("%d", &n);
        cnt = 0;
        for (int i = 1; i <= n; ++i) {
            int x, y;
            cin >> x >> y;
            if (check(x, x + y - 1)) {
                l[++cnt] = x; r[cnt] = x + y - 1;
            } else {
                for (int j = 0; j <= cnt; ++j) {
                    if (check(r[j] + 1, r[j] + y)) {
                        l[++cnt] = r[j] + 1; r[cnt] = r[j] + y;
                        break;
                    }
                }
            }
            cout << l[i] << " " << r[i] << endl;
            //用于维持l数组从小到大。
            for (int j = 1; j < cnt; ++j)
                for (int k = j + 1; k <= cnt; ++k)
                    if (l[j] > l[k]) swap(l[j], l[k]), swap(r[j], r[k]);
        }
    }

    B题:Minimum and Maximum

      题目链接:http://codeforces.com/contest/730/problem/B

      题意:

        其实就是个模拟人机询问,给定一个数组A,你不知道其内容,然后你输出“? x y”代表向电脑询问A[x]和A[y]的关系,电脑输入>,<,=表示其关系,但要求输入的询问个数不能超过[3*n/2]-2个。最后用“! min max”代表输出结果,输出数组中第几个数是最小值,第几个数是最大值。

      分析:

        做法就是模拟归并,对于每个数组询问i*2和i*2+1的关系,将大的值放入一个集合,小的放入另一个,这样询问n/2次。如果n为奇数的话,把最后一个放入这两个集合。然后分别对每个集合询问,这个直接就询问一遍问出对应的最大值或最小值就好了。结果我们错在输出的内容没有没有从缓冲区调出,也是醉了。

    #include <bits/stdc++.h>
    
    std::vector<int> up, down;
    
    int query(int i, int j) {
        if (i == j) return 0;
        printf("? %d %d
    ", i + 1, j + 1);
        fflush(stdout);//这句话必须加,作用是立刻将printf的内容输出,不加这句话printf会先将输出内容存放到缓冲区,然后等时间片轮转到输出程序时在输出
        char ans[3]; scanf("%s", ans);
        if (ans[0] == '<') return -1;
        else if (ans[0] == '=') return 0;
        else return 1;
    }
    
    int main() {
        int T; scanf("%d", &T);
        for (; T --; ) {
            int n; scanf("%d", &n);
            up.clear(); down.clear();
            for (int i = 0; i < n / 2; ++ i) {
                if (query(i * 2, i * 2 + 1) < 0) {
                    up.push_back(i * 2 + 1);
                    down.push_back(i * 2);
                }
                else {
                    down.push_back(i * 2 + 1);
                    up.push_back(i * 2);
                }
            }
            if (n % 2 != 0) {
                up.push_back(n - 1);
                down.push_back(n - 1);
            }
            int maxindex = up[0], minindex = down[0];
            for (int i = 1; i < (int)up.size(); ++ i) {
                if (query(up[i], maxindex) > 0)
                    maxindex = up[i];
            }
            for (int i = 1; i < (int)down.size(); ++ i) {
                if (query(down[i], minindex) < 0)
                    minindex = down[i];
            }
            printf("! %d %d
    ", minindex + 1, maxindex + 1);
            fflush(stdout);
        }
    }

    J题:Bottles

      题目链接:http://codeforces.com/contest/730/problem/J

      题意:

        给出每个瓶子现在装得水的体积,然后给出每个瓶子的体积,然后瓶子之间可以互相倒水,每倒出一体积水花费为1,然后问最少用几个瓶子装这些水,然后最少花费是多少。

      分析:最少用几个桶很简单能求出来。然后背包出这些桶花费最少,比赛时简直智障,一直想贪心,都没往背包上想。

      

    #include <bits/stdc++.h>
    using namespace std;
    struct qwe
    {
        int a,b;
    } e[110];
    int cmp(qwe x,qwe y)
    {
        return (x.b>y.b || (x.b==y.b && x.a>y.a));//体积大的排序,如果体积相同就按照已经有水多的的在前面
    }
    int cmp1(qwe x,qwe y)//按照体积小的排序
    {
        return (x.b<y.b);
    }
    int dp[110][10010],s[110];
    int main()
    {
        //freopen("C:\Users\acer\Desktop\in.txt","r",stdin);
        int n;
        scanf("%d",&n);
        int sum=0;//总共有多少水
        for(int i=1;i<=n;i++) 
            scanf("%d",&e[i].a),sum+=e[i].a;
        for(int i=1;i<=n;i++) 
            scanf("%d",&e[i].b);
        sort(e+1,e+1+n,cmp);
        int t=0,q=0;
        int ans;
        for(int i=1;i<=n;i++)
        {
            t+=e[i].b;
            if(t>=sum)
            {
                ans=i;
                break;
            }
        }//找出最少的桶数
        sort(e+1,e+1+n,cmp1);
        for(int i=1;i<=n;i++) 
            s[i]=s[i-1]+e[i].b;
        memset(dp,0xBf,sizeof(dp));
        dp[0][0]=0;//dp[j][k]表示j个桶,最多装多少水
        for(int i=1;i<=n;i++)//用多少桶
        {
            for(int j=min(i,ans);j>0;j--)
                for (int k=s[i];k>=e[i].b;k--)
                {
                        dp[j][k]=max(dp[j][k],dp[j-1][k-e[i].b]+e[i].a);
                }
        }
        int fin=0;
        for (int k=s[n];k>=sum;k--)
            fin=max(fin,dp[ans][k]);
        printf("%d %d
    ",ans,sum-fin);
        return 0;
    }
  • 相关阅读:
    Medium | LeetCode 142. 环形链表 II
    Easy | LeetCode 141. 环形链表
    Hard | LeetCode 23. 合并K个升序链表 | 分治 | 优先队列
    std(19)内置算法find find_if
    stl(18)内置算法for_each transform
    C++引用和指针比较 指针常量和常量指针
    #pragma once和#ifndef用法
    c++变量的一些注意点 extern关键字的使用
    比特 字节 地址 类型 编码 32位 64位
    stl(16)stl内置的一些函数对象
  • 原文地址:https://www.cnblogs.com/137033036-wjl/p/5994231.html
Copyright © 2020-2023  润新知