2017中国大学生程序设计竞赛 - 网络选拔赛

本文精选了解析HDU ACM竞赛中的部分题目,包括Friend-Graph与CaoHaha’s staff等,通过深入浅出的方式介绍了如何利用图论与二分查找等算法解决问题。

题目链接


01:http://acm.hdu.edu.cn/showproblem.php?pid=6150
02:http://acm.hdu.edu.cn/showproblem.php?pid=6151
03:http://acm.hdu.edu.cn/showproblem.php?pid=6152
04:http://acm.hdu.edu.cn/showproblem.php?pid=6153
05:http://acm.hdu.edu.cn/showproblem.php?pid=6154
06:http://acm.hdu.edu.cn/showproblem.php?pid=6155
07:http://acm.hdu.edu.cn/showproblem.php?pid=6156
08:http://acm.hdu.edu.cn/showproblem.php?pid=6157
09:http://acm.hdu.edu.cn/showproblem.php?pid=6158
10:http://acm.hdu.edu.cn/showproblem.php?pid=6159
11:http://acm.hdu.edu.cn/showproblem.php?pid=6160
比赛时两题入账,但我觉得这就是发挥出我们队的实力了,比赛的时候感觉挺充实的,一直都在思考。

一些题解


03 Friend-Graph

 题目是说给你一个关系图,第i个人和其他n - i个人的关系给出,1代表能成为朋友,0代表不能成为朋友,当3个人及以上没有朋友或者三个及以上都互相是朋友时就是bad team否则就是good team。
 本题一开始妄图用强连通果断超内存,后来直接建两张图,互为盆友的连通,不为朋友的连通,然后只要每次搜一遍看看朋友的盆友是否连通即可,如果连通直接判断为不行。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 3003;
bool g[maxn][maxn];
inline int read()
{
    int pre=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){pre=pre*10+ch-'0';ch=getchar();}
    return pre*f;
}
#define  clr(a,b) memset(a,b,sizeof(a))
bool solve(int n)
{
    for(int i=1;i<=n-2;i++)
    {
        vector<int>G1,G2;
        G1.clear();
        G2.clear();
        for(int j=i+1;j<=n;j++)
        {
                if(g[i][j]==1) G1.push_back(j);
                else G2.push_back(j);
        }
        for(int j=0;j<G1.size();j++)
        {
            for(int k=j+1;k<G1.size();k++)
                if(g[G1[j]][G1[k]]==1)
                        {

                        return 0;
                }
        }
        for(int j=0;j<G2.size();j++)
        {
            for(int k=j+1;k<G2.size();k++)
                if(g[G2[j]][G2[k]]==0)
                    {
                        return 0;

                    }
        }
    }
    return 1;
}
int main()
{
    int t = read();
    while(t--)
    {
        clr(g,0);
        int n = read();
        for(int i=1;i<=n-1;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                int x = read();
                if(x==1)
                g[i][j]=1;

            }
        }
        printf("%s\n",solve(n)?"Great Team!":"Bad Team!");
    }
    return 0;
}

05 CaoHaha’s staff

 题目是说给你一个物品的大小,然后给你一个方格纸告诉你每一笔只能横着或者竖着画一个单位线段,或者走正方形的斜边画一道根号2单位的线,问最少画几道可以覆盖大于等于题目给定的物品大小的面积。
 运用二分答案,看看一定的笔数最多可以覆盖多少大的面积。如果当前笔数是偶数那么将它除以2,如果还是偶数就是mid/2/2 * mid / 2/ 2 * 2,如果奇数就是mid/2/2 * (mid/2/2 + 1)*2。如果当前笔画数是奇数,就把当前数减一然后和偶数时一样,最后再加上mid/2/2(意思就是一条边向外扩展一个梯形)就是奇数时的最大覆盖数。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int t;
    scanf("%d", &t);
    while(t--)
    {
        LL n;
        scanf("%I64d", &n);
        LL l = 4, r = 1e6;
        LL az = n;
        while(r >= l)
        {
            LL ans;
            LL mid = (l + r) / 2;
            LL  midd = mid;
            if(mid % 2 == 0)
            {
                mid /= 2;
                if(mid % 2 == 0)
                {
                    mid /= 2;
                    ans = mid * mid * (LL)2;
                }
                else
                {
                    mid /= 2;
                    ans = mid * (mid + 1) * (LL)2;
                }
            }
            else
            {
                mid /= 2;
                if(mid % 2 == 0)
                {
                    mid /= 2;
                    ans = mid * mid * (LL)2;
                }
                else
                {
                    mid /= 2;
                    ans = mid * (mid + 1) * (LL)2;
                }
                ans += mid;
            }
            if(ans < n)
            {
                l = midd + 1;
            }
            else if(ans >= n)
            {
                az = midd;
                r = midd - 1;
            }
        }
        printf("%I64d\n", az);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值