HNUST 辅导上机(模拟)

题目描述

又到了辅导学弟学妹们上机的时候了,学长们都非常踊跃报名。那么问题来了,如何安排上机呢?现在将问题简化一下:一共需要n节课(编号从1到n)的辅导上机,正好有n位学长(编号从1到n)报名,用二维矩阵A表示学长们的情况,A[i][j]表示第i个学长第第j节课是否有时间(1表示有时间,0表示忙)。为了进一步简化问题,假设一定存在将学长们按一定顺序排列后,前一位学长的合适时间集合包含后一位学长(也就是后一位学长哪节课有时间,那么前一位学长一定有时间,反过来就不一定了)。每节课都需要有学长辅导,同时为了满足大家辅导上机的热情,规定每个人恰好参与一次。现在问聪明的你能找到这样的方案吗?(能输出“Yes”,不行输出“No”)

输入

包含多组数据(数据组数小于200),每组数据第一行输入n(1<=n<=20),表示有n节课需要辅导和n位学长报名,接下来是n行n列矩阵表示学长们的情况(0表示忙,1表示有时间)。数据保证一定满足题目假设。

输出

每组数据输出一行,能找到方案输出“Yes”, 不能找到这样的方案输出“No”。

样例输入
5
0 0 0 0 1
0 1 1 1 1
0 1 1 1 1
1 1 1 1 1
0 0 0 0 1
3
1 1 1
1 1 0
0 1 0

样例输出
No
Yes

提示

如样例中1,用集合表示每一位学长的合适时间,分别是{5} 、{2,3,4,5} 、{2,3,4,5} 、{1,2,3,4,5} 、{5} ,他们按照一定顺序排列后满足关系:{1,2,3,4,5} ⊇ {2,3,4,5} ⊇ {2,3,4,5}⊇ {5} ⊇ {5} 找不到方案让每个人都参与一次,所以输出No。

提示:往题目给定限制(存在包含关系)思考,也就没那么难。来源:唐志强

链接:http://acm.hnust.edu.cn/JudgeOnline/problem.php?id=1744

思路:根据包含关系,知道排完序后,后面的学长有的前面的学长肯定有,那么就从后面的学长开始安排,安排掉一个少一个,同时其他学长该时间不必辅导,则置为0,一旦安排的过程中出现有学长的全部都是0,则安排不了。

代码:

//我是从小到大
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
struct shang
{
    int a[30];
    int cnt;
    bool operator < ( const shang &b ) const   //按能安排的时间的多少从小到大排序
    {
         return cnt < b.cnt;
    }
}xue[30];
int main()
{
    int n;
    while(cin >> n)
    {
        for(int i=0; i<n; i++)
        {
            xue[i].cnt = 0;
            for(int j=0; j<n; j++)
            {
                cin >>xue[i].a[j];
                if(xue[i].a[j] == 1)
                    xue[i].cnt++;
            }
        }
        sort(xue,xue+n);
        int flag = 1;
        for(int i=0; i<n; i++)
        {
            int j=0;
            while(xue[i].a[j] == 0 && j != n)   //由于从最少的开始找,只要找第一个有空的时间
            {
                j++;
            }
            if(j == n)         //该学长全都没有空
            {
                cout << "No" << endl;
                flag = 0;
                break;
            }
            for(int k=0; k<n; k++)    //该时间的其他学长不需要辅导
            {
                xue[k].a[j] = 0;
            }
            memset(xue[i].a, 0 ,sizeof xue[i].a);   //安排完一个学长了
        }
        if(flag)
            cout <<"Yes" << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值