2019中山大学程序设计竞赛

hdu6512Triangle

theme:判断n个数中可否存在构成三角形的三个数。

solution:对于n个数找构成三角形的三个数的题,按数据范围有不同解法。想法是将这n个数从小到大排序,(下标从0开始),之后从i=1开始,将i,i+1作为三角形较大的两边,判断它们的差(正值)d是否<a[i-1]即可,因为一旦<则满足条件,一旦>,则d更>i-1之前的数了(要使c-b<a,则找到c-b最小值和a最大值,由于c-b最小处可能取多个,所以我们就遍历每一个c-b即可,这样c-b最小即为每个相邻数之差)。这样做时间复杂度就是排序的时间o(nlog(n)),但该题n较大,又存在多组测试数据,o(nlog(n))关闭流同步才1994ms险过,所以考虑进一步优化:

由上述思路转化为两边之和大于第三边的话,相邻两数a[i],a[i+1]之和要是<a[i+2]也一定小于它后面的数,所以遍历时,极端情况就是1,2,3,5,8,13、、、刚好=情况,由斐波那契数列算出n到50左一点就超int了,所以可看n>=50时一定存在三个数(排序后)组成三角形。

#include <cstdio>
#include <list>
#include<iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

int a[5000010];
ll fib[200];

int main()
{
    ios::sync_with_stdio(false);

//    fib[0]=1,fib[1]=1;
//    for(int i=2;i<=100;++i)
//        fib[i]=fib[i-1]+fib[i-2];
//    cout<<fib[50];

    int n;
    while(cin>>n)
    {
        for(int i=0;i<n;++i)
            cin>>a[i];
        if(n<2)
        {
            cout<<"NO\n";
            continue;
        }
        if(n>=50)
        {
            cout<<"YES\n";
            continue;
        }
        sort(a,a+n);
        int flag=0;
        for(int i=1;i<n-1;++i)
        {
            int b=a[i+1]-a[i];
            if(b<a[i-1])
            {
                flag=1;
                break;
            }
        }
        if(flag)
            cout<<"YES\n";
        else
            cout<<"NO\n";
    }
    return 0;
}

hdu6518Clumsy Keke

theme:由矩阵形式给定三视图,一小格代表体积为1.问满足该三视图的图形的最大体积为多少?

                  

solution:题目输入并不是直接按主视图、左视图、俯视图角度给的,所以先确定一下x,y,z轴方向。想象一个由x*y*z的格子堆成的正方体。对于每一视图,如主视图,该格上有图形,则表示它及它后面的格子都可能放小正方体。这样由三个视图的&关系可以确定哪些格子上是可以放小正方体的。

#include <cstdio>
#include <list>
#include <cstring>
#include<iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

int Front[110][110];
int Left[110][110];
int Top[110][110];
int ans[110][110][110];

int main()
{
    int mx,my,mz;
    while(~scanf("%d%d%d",&mx,&my,&mz))
    {
        for(int i=0;i<mx;++i)
            for(int j=0;j<my;++j)
                scanf("%d",&Front[i][j]);
        for(int i=0;i<my;++i)
            for(int j=0;j<mz;++j)
                scanf("%d",&Left[i][j]);
        for(int i=0;i<mz;++i)
            for(int j=0;j<mx;++j)
                scanf("%d",&Top[i][j]);

        for(int i=0;i<mx;++i)
            for(int j=0;j<my;++j)
                for(int z=0;z<mz;++z)
                    ans[i][j][z]=Front[i][j];
        for(int j=0;j<my;++j)
            for(int z=0;z<mz;++z)
               for(int i=0;i<mx;++i)
                    ans[i][j][z]&=Left[j][z];
        for(int z=0;z<mz;++z)
            for(int i=0;i<mx;++i)
                for(int j=0;j<my;++j)
                    ans[i][j][z]&=Top[z][i];

        int res=0;
        for(int i=0;i<mx;++i)
            for(int j=0;j<my;++j)
                for(int z=0;z<mz;++z)
                    res+=ans[i][j][z];
        printf("%d\n",res);
    }
}

猜你喜欢

转载自blog.csdn.net/wangqianqianya/article/details/89414285