手速练习8


CodeForces - 18A - Triangle

题意:给出3个点,其坐标都是整数,如果这三个点能组成直角三角形输出"RIGHT",如果不是直角三角形,但是将某个点的坐标移动一个整数的位置(上下左右),移动后三个点组成直角三角形则输出"ALMOST",都不是则输出"NEITHER"

由于数据较小,枚举即可,但是要注意在移动点时,不要与其他点重合

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 4
double x[M],y[M],line[M];//line是三角形的边
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
double dis(int a,int b)//求两点间的距离
{
    return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
}
int main()
{
    scanf("%lf%lf%lf%lf%lf%lf",&x[1],&y[1],&x[2],&y[2],&x[3],&y[3]);
    line[1]=dis(1,2);
    line[2]=dis(1,3);
    line[3]=dis(2,3);
    sort(line+1,line+4);
    if(line[1]+line[2]==line[3]) //a^2+b^2=c^2
    {
        printf("RIGHT\n");
        return 0;
    }

    for(int i=1;i<=3;i++)   //枚举每个点
    {
        for(int k=0;k<4;k++)//四个方向
        {
            x[i]+=dx[k]; y[i]+=dy[k];
            bool f=true;
            for(int j=1;j<=3;j++)//防止与其他点重合
            {
                if(j==i) continue;
                if(x[i]==x[j]&&y[i]==y[j]) {f=false;break;}
            }
            if(f)
            {
                line[1]=dis(1,2);
                line[2]=dis(1,3);
                line[3]=dis(2,3);
                sort(line+1,line+4);
                if(line[1]+line[2]==line[3])
                {
                    printf("ALMOST\n");
                    return 0;
                }
            }
            x[i]-=dx[k]; y[i]-=dy[k];
        }
    }
    printf("NEITHER\n");
    return 0;
}


CodeForces - 16C - Monitor

题意:现有屏幕长和宽分别为X,Y,问能否将其切割为长宽比例为a:b的一块屏幕,要使切出来的屏幕面积尽量大

解析:注意长宽是不能互换的,此题最坑之处在于若a和b有最大公约数要将a和b都除以最大公约数,

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 100005
ll a,b,x,y;
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    cin>>a>>b>>x>>y;
    ll g=gcd(x,y);
    x=x/g;y=y/g;
    if(x>a||y>b)//如果x>a||y>b是切不出来的,因为此时屏幕面积最小a*b,其余情况至少能切为a*b
    {
        cout<<0<<" "<<0<<endl;
        return 0;
    }
    ll ansa=0,ansb=0;
    if(x>=y)
    {
        //if(a<b) swap(a,b);
        ll tmp=a/x;
        a=tmp*x;    //确定能到达的宽的最大值,用它去试长度
        while(b<tmp*y)//满足宽为a的长tmp*y大于b,此时通过缩小宽度a来缩小所需的长度继续试
        {
            a-=x;
            tmp--;
        }
        ansa=a;
        ansb=tmp*y;
    }else{
        //if(a>b) swap(a,b);
        ll tmp=b/y;
        b=tmp*y;
        while(a<tmp*x)
        {
            b-=y;
            tmp--;
        }
        ansa=tmp*x;
        ansb=b;
    }
    if(ansa<0||ansb<0)
        cout<<0<<" "<<0<<endl;
    else
        cout<<ansa<<" "<<ansb<<endl;
    return 0;
}


CodeForces - 22B - Bargaining Table

题意:有n*m房间,用01矩阵表示,0表示空闲,1表示有东西在此位置,问此房间里最大能放一个边长多大的矩形桌子

解析:枚举桌子大小即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 35
int n,m;
char str[M][M];
bool solve(int x,int y)//x,y为桌子的长和宽
{
    for(int i=0;i+x-1<n;i++)
    {
        for(int j=0;j+y-1<m;j++) //(i,j)为桌子左上角
        {
            bool f=true;
            for(int w=0;w<x;w++)
            {
                for(int h=0;h<y;h++)//去检查桌子所在位置的每个点
                {
                    int xx=i+w;
                    int yy=j+h;
                    if(str[xx][yy]=='1') f=false;
                }
            }
            if(f==true) return true;
        }
    }
    return false;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
        scanf("%s",str[i]);

    int ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(solve(i,j))
            {
                ans=max(ans,2*i+2*j);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

CodeForces - 18B -  Platforms

题意:在一个直线上有n个平台。 第k个平台(平台从1开始编号)是坐标为[(k-1)*m,(k-1)*m+L]且(l <m)的一段。 Bob 从坐标为0点开始沿着直线跳跃,每次跳跃移动d个单位, 找出鲍勃将落下的点的坐, 如果Bob不在平台上,Bob就会掉下来,在平台的边缘,不算掉下。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 1005
ll n,d,m,l;
int main()
{
    cin>>n>>d>>m>>l;
    ll low=0,hig=l;
    ll pos=0,k=1;
    while(1)  //当前循环中Bob位于pos,
    {
        if(k>n) break;//k是当前到了哪块平台
        low=(k-1)*m;  //low,hig平台两端
        hig=(k-1)*m+l;
        if(pos<=hig) pos=pos+((hig-pos)/d+1)*(d);//如果Bob在平台上,那么让Bob走(hig-pos)/d+1步使得Bob离开当前k平台
        if(k<n&&pos<k*m)//平台走完,或到达不了下一个平台就退出
        {
            break;
        }
        k++;
    }
    cout<<pos<<endl;
    return 0;
}


CodeForces - 4B - Before an Exam

题意:总共有时间sum,有d天,每天学习时间不能少于L[i],每天学习时间不能超过R[i],问能否成功的将sum分到d天,能的话要输出每天的学习时间

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 35
int n,sum,l[M],r[M],ans[M],totl[M],totr[M];//totl[i],totr[i]分别是到第i天的最少、最多学习时间和
int main()
{
    scanf("%d%d",&n,&sum);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&l[i],&r[i]);
        totl[i]=totl[i-1]+l[i];
        totr[i]=totr[i-1]+r[i];
    }
    if(sum<totl[n]||sum>totr[n])
    {
        cout<<"NO"<<endl;
    }else{
        int tot=0;
        for(int i=n;i>=1;i--) //从后往前,确定每天时间
        {
            for(int k=l[i];k<=r[i];k++)//枚举当前天用时间k是否可以
            {
                if((sum-(tot+k))>=totl[i-1]&&(sum-(tot+k))<=totr[i-1])//sum-(tot+k)是给前面i-1天的总时间
                {
                    tot+=k;
                    ans[i]=k;
                    break;
                }
            }
        }
        cout<<"YES"<<endl;
        for(int i=1;i<n;i++)
            printf("%d ",ans[i]);
        printf("%d\n",ans[n]);
    }
    return 0;
}



CodeForces - 6C - Alice, Bob and Chocolate

题意:有n个巧克力,从左到右摆开,每块需要a[i]个单位时间能吃完,Alice从左边开始吃,Bob从右边开始吃,若两个人同时遇到同一块巧克力让Alice吃,问每个人分别吃了几个

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 100005
int n,t[M];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&t[i]);
    
    if(n==1)//只有一个A吃
    {
        cout<<1<<" "<<0<<endl;
        return 0;
    }
    int a=1,b=n;
    ll tima=t[1];//tima为A吃到第a块花的时间
    ll timb=t[n];//timb为B吃到第B块花的时间
    while(a+1<b)//Alice在吃序号为a的,Bob在吃序号为b的
    {
        if(tima>timb)//Alice吃完第a块要到tima,而Bob到timb就吃完第b块了,所以Bob再吃一块
        {
            b--;
            timb+=t[b];
        }else{
            a++;
            tima+=t[a];
        }
    }
    cout<<a<<" "<<n-a<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值