编程练习赛41:题目1 : 比赛日程安排

题目1 : 比赛日程安排

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

H国编程联赛中有N只队伍,编号1~N。 他们计划在2018年一共进行M场一(队)对一(队)的比赛。

为了让参赛队员能得到充分的休息,联赛组委会决定:每支队伍连续两场比赛之间至少间隔一天。也就是如果A队1月1日参加了一场比赛,那么下一场比赛最早安排在1月3日。

给定M场比赛的时间和参赛的两支队伍,请你判断这个日程安排是否可行。

输入

第一行包含一个整数T,代表测试数据组数。(1 ≤ T ≤ 10)

对于每组数据,第一行包含两个整数N和M。(1 ≤ N ≤ 50, 1 ≤ M ≤ 1000)

以下M行每行描述一场比赛,包含比赛日期(格式MM-DD),以及2支参赛队伍的编号。

输出

对于每组数据输出YES或者NO,代表日程安排是否可行。

样例输入
2
3 3
01-01 1 2
01-03 1 3
01-05 2 3
4 4
02-01 4 3
01-30 4 1
01-31 1 2
01-30 2 3
样例输出
YES
NO

思路:

输入数据进行保存,然后统计每只队伍的比赛日期,只要有一只队伍的比赛时间不满足要求,此次结果就是false,打印NO。

这次难点有对输入数据的处理存储想了很久,处理的时候对每组数据进行处理判断,得到结果后再对下一次的输入数据进行处理,处理的思路是统计每一只队伍的比赛时间,然后转化为整数,这里需要注意可能相差很多月份,所以要使用/100对月份进行判断,这里的依据是日期的格式是固定的,就可以对输入的xx-yy进行处理,更好的方法是使用scanf(%s-%d %d),直接将输入转化为整数,节省很多工作量。

转化为整数后,月份一样的直接前后相减,月份相差很大的肯定不会重复,所以肯定是对的,月份相差为1的需要重点对待,使用的方法是i所在的月份日期 + i -1月天数 - 100。

总结收获:输入的处理,stoi转化为整数,直接将字符串输入就可以转化为整数,string tmp,int i =stoi(tmp);

scanf的运用。

因为每一组数据中的队伍只要有一个安排不对,那么整个数组的安排就是错的,需要返回false,然后马上break,结束当前循环,因为不break的话,后面会将result变量修改为true;

还有需要注意的地方是N只队伍,使用的时候是第i只队伍,所以数组的大小是N+ 1,访问的时候i要从1开始访问。

自己写的版本,通过了是90/100

#include<vector>
#include<algorithm>
#include<string>
#include<iostream>

using namespace std;
struct node {
    string day;
    int left;
    int right;

    node(string s, int x, int y) :day(s), left(x), right(y) {}
};
struct nm {
    int N;
    int M;
    bool result;
    nm(int x,int y,bool res = true):N(x),M(y),result(res) {}
};
vector<int> month{0,31,28,31,30,31,30,31,31,30,31,30,31};

bool isOk(vector<string> &alltime) {
    if (alltime.size() == 0) {
        return false;
    }
    vector<int> timeint;
    for (int i = 0; i < alltime.size();++i) {
        string tmp;
        for (int j = 0; j < 5; ++j) {//xx-yy

            if (j == 2) {
                continue;

            }
            tmp.push_back(alltime[i][j]);

        }
        int tmpint = stoi(tmp);
        timeint.push_back(tmpint);
    }
    sort(timeint.begin(), timeint.end());
    //for (int i : timeint) {
    //    cout << i << endl;
    //}
    for (int i = 0; i < timeint.size(); ++i) {
        if (i != 0) {
            int i1, i2;
            i1 = timeint[i - 1] / 100;
            i2 = timeint[i] / 100;
            if (i1 == i2) {
                //cout << timeint[i] - timeint[i - 1] << endl;
                if (abs(timeint[i] - timeint[i - 1]) < 2) {
                    return false;
                }
                //cout << timeint[i] - timeint[i - 1] << endl;
            }
            else if ((i2 - i1) > 1) {
                continue;
            }
            else  if(i2 - i1 == 1){
                int a = timeint[i] + month[i1] - 100;
                if (abs(a - timeint[i - 1]) < 2) {
                    return false;
                }
                //cout << a - timeint[i - 1] << endl;
            }

        }
    }
    return true;
}
void judge(vector<node> &input, nm &NMRes) {
    int N = NMRes.N;
    int M = NMRes.M;
    //bool res = NMRes.result;
    vector<vector<string>> totalTime(N + 1,vector<string> ());//每只队伍所有的比赛时间
    for (int i = 0; i < M; ++i) {
        totalTime[input[i].left].push_back(input[i].day);
        totalTime[input[i].right].push_back(input[i].day);
    }
    //判断是否每只队伍都只相隔一天的比赛日期
    for (int i = 1; i <= N; ++i) {
        if (isOk(totalTime[i])) {
            NMRes.result = true;
        }
        else {
            NMRes.result = false;
            break;
        }
    }
}

int main() {
    int T;//T组测试数据
    int N;//N只队伍
    int M;//M场比赛,string
    cin >> T;
    nm nmTmp(0, 0);
    vector<nm> nmVec(T, nmTmp);//存输入的队伍和比赛总次数以及最后的判断结果
    //int i = 0;
    vector<node> inputOfOne;//每组比赛的数据
    vector<vector<node>> inputTotal;//所有比赛的数据
    for (int i = 0; i < T; ++i) {
        cin >> nmVec[i].N >> nmVec[i].M;
        for (int j = 0; j < nmVec[i].M; ++j) {//输入一组数据
            node tmpNode("",0,0);
            cin >> tmpNode.day >> tmpNode.left >> tmpNode.right;
            inputOfOne.push_back(tmpNode);
        }
        inputTotal.push_back(inputOfOne);
        vector<node>().swap(inputOfOne);
    }
    //对每组数据进行judge判断
    for (int i = 0; i < T; ++i) {
        judge(inputTotal[i], nmVec[i]);
    }
    //输出结果
    for (int k = 0; k < T; ++k) {
        if (nmVec[k].result) {
            cout << "YES" << endl;
        }
        else {
            cout << "NO" << endl;
        }

    }
    system("pause");
}

自己写的版本

优化版本:ac

#include <iostream>
#include <stdio.h>
#include <utility>
#include <algorithm>
using namespace std;

int months[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
int main() {
    int T;
    cin >> T;
    while (T--) {
        int N, M;
        cin >> N >> M;
        vector<vector<pair<int,int>> > v(N + 1);
        for (int i = 0; i < M; ++i) {
            int month, day, c1,c2;
            scanf("%d-%d %d %d", &month, &day, &c1, &c2);
            v[c1].push_back(make_pair(month, day));
            v[c2].push_back(make_pair(month, day));
        }
        bool flag = true;
        for (int i = 1; i < N + 1; ++i) {
            sort(v[i].begin(), v[i].end());
            for (int j = 1; j < v[i].size(); ++j) {
                if (v[i][j].first == v[i][j - 1].first) {
                    if (v[i][j].second - v[i][j - 1].second < 2) {
                        flag = false;
                        break;
                    }
                }
                else if (v[i][j].first - v[i][j - 1].first > 1) {
                    continue;
                }
                else {
                    if (v[i][j].second + months[v[i][j - 1].first - 1] - v[i][j - 1].second < 2) {
                        flag = false;
                        break;
                    }
                }
            }
            if (flag == false) {
                cout << "NO" << endl;
                break;
            }
        }
        if (flag == true) {
            cout << "YES" << endl;
        }
    }
}

时间: 2024-11-13 06:42:05

编程练习赛41:题目1 : 比赛日程安排的相关文章

HihoCoder1670 : 比赛日程安排([Offer收割]编程练习赛41)(模拟)

描述 H国编程联赛中有N只队伍,编号1~N. 他们计划在2018年一共进行M场一(队)对一(队)的比赛. 为了让参赛队员能得到充分的休息,联赛组委会决定:每支队伍连续两场比赛之间至少间隔一天.也就是如果A队1月1日参加了一场比赛,那么下一场比赛最早安排在1月3日. 给定M场比赛的时间和参赛的两支队伍,请你判断这个日程安排是否可行. 输入 第一行包含一个整数T,代表测试数据组数.(1 ≤ T ≤ 10) 对于每组数据,第一行包含两个整数N和M.(1 ≤ N ≤ 50, 1 ≤ M ≤ 1000)

[Offer收割]编程练习赛11 题目2 : 物品价值

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi现在有n个物品,每个物品都有一个价值.并且这n个物品总共有m个不同的属性,每个物品都具有其中若干属性. 小Ho要从中选出若干物品,满足每个属性都正好有奇数个物品拥有,且被选出的物品价值总和最大.你能帮助小Ho完成任务么? 输入 第一行一个数T(<=10),表示数据组数.对于每一组数据: 第一行两个数n,m(1<=n<=1000,m<=10) 接下来每两行描述一件物品.对于每一件物品: 第一行两个数v

[Offer收割]编程练习赛11 题目3 : 岛屿3

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 H国正在进行一项持续N周的填海造岛工程.整片工程海域可以被看作是1000x1000的网格. 每周都有一块1x1的单位方格海域被填成陆地.如果我们将连成一片的陆地(一块单位方格与它上下左右4个单位方格是相连的)视为岛屿,H国想监测每周末整片海域中一共存在有多少个岛屿,以及这些岛屿的总面积和总周长各是多少. 假设工程持续三周,第一周被填的海域坐标是(0, 0),那么第一周结束后有1座岛屿.总面积是1.总周长是4: #..

[Offer收割]编程练习赛11 题目4 : 排队接水

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 有n个小朋友需要接水,其中第i个小朋友接水需要ai分钟. 由于水龙头有限,小Hi需要知道如果为第l个到第r个小朋友分配一个水龙头,如何安排他们的接水顺序才能使得他们等待加接水的时间总和最小. 小Hi总共会有m次询问,你能帮助他解决这个问题吗? 假设3个小朋友接水的时间分别是2,3,4.如果他们依次接水,第一位小朋友等待加接水的时间是2,第二位小朋友是5,第三位小朋友是9.时间总和是16. 输入 第一行一个数T(T<=1

[Offer收割]编程练习赛12 题目3 : 矩形分割

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi有一块由NxM个单位正方形组成的矩形.现在小Ho在某些单位正方形上画了一道分割线,这条分割线或者是单位正方形的主对角线(用'\'表示),或者是副对角线(用'/'表示). 现在小Hi想知道这些分割线把NxM的矩形分割成了多少块区域. 例如 /\/ 就把2x2的矩形分成了5个区域. /\/\ / \/ 把3x4的矩形分成了7个区域. 输入 第一包含两个整数N和M.(1 <= N, M <= 100) 以下N行每行包

[Offer收割]编程练习赛3 - 题目3 : 智力竞赛

智力竞赛 Problem's Link ---------------------------------------------------------------------------- Mean: 略(中文题). analyse: 比赛中最先想到的是三维dp,但思考后发现可以压缩为二维,状态转移方程: dp[i][j]=min(dp[i][j],dp[i][j-(right+fault)]+right) 其中dp[i][j]表示: 到通过第i关为止,在总共只有j次答题机会的情况下,总共至

[Offer收割]编程练习赛12 题目4 : 寻找最大值

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定N个数A1, A2, A3, ... AN,小Ho想从中找到两个数Ai和Aj(i ≠ j)使得乘积Ai × Aj × (Ai AND Aj)最大.其中AND是按位与操作. 小Ho当然知道怎么做.现在他想把这个问题交给你. 输入 第一行一个数T,表示数据组数.(1 <= T <= 10) 对于每一组数据: 第一行一个整数N(1<=N<=100,000) 第二行N个整数A1, A2, A3, ... AN

[Offer收割]编程练习赛12 题目1 : 歌德巴赫猜想

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 哥德巴赫猜想认为"每一个大于2的偶数,都能表示成两个质数之和". 给定一个大于2的偶数N,你能找到两个质数P和Q满足P<=Q并且P+Q=N吗? 输入 一个偶数N(4 <= N <= 1000000) 输出 输出P和Q.如果有多组解,输出P最小的一组. 样例输入 10 样例输出 3 7 思路 判断和为N两个数是否为素数 代码 1 import java.util.Scanner; 2 3 pu

[Offer收割]编程练习赛12 题目2 : 一面砖墙

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi的学校的教学楼前有一面砖墙.这面墙由N层砖砌成,其中从上到下第i层包含Ci块高度相同但宽度不同的砖. 例如下图所示的这面墙,由3层砖砌成.其中第1层包含3块砖,从左到右宽度依次是6.4和3:第2层包含4块砖,从左到右依次宽度依次是4.4.2和3:第3层包含3块砖,从左到右宽度依次是5.6和2. +------------+ | 6 | 4 |3 | +------------+ | 4 | 4 |2|3 | +-