0
点赞
收藏
分享

微信扫一扫

acwing----春季每日一题2022篇(二)

雨鸣静声 2022-03-25 阅读 43
算法

春季每日一题2022篇(二)

三角形(枚举)

题目链接

题目大意
题目要我们在一堆二维点中,选择三个点使得构成的三角形面积最大。(三角形有一条边与 x 轴平行,且有另一条边与 y 轴平行。)

解题思路
如图 ,我们选定一个点a,对于一个点我们令其x与a相同为b , 最后一个点我们枚举与a的y相同的点。
在这里插入图片描述
代码:

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

const int N = 1010;

struct point{
    int x ,y;
}p[N];

int n ;

double solve(point a, point b ,point c){
    int y = b.y - a.y , x = c.x - a.x;
    return abs(y * x) / 2.0;
}

int main(){
    cin>>n;
    for(int i = 0 ;i < n; ++i)cin>>p[i].x>>p[i].y;
    
    double ans = 0.0 ;
    for(int i = 0 ;i < n ; ++i)
        for(int j = 0 ; j < n ; ++j)
            for(int k = 0 ; k < n ; ++k)
                if(p[j].x == p[i].x && p[k].y == p[i].y)
                    ans = max(ans , solve(p[i],p[j],p[k]));
    cout<<(int)(ans * 2.0)<<endl;
    
    return 0;
}

社交距离 I (分类讨论 + 贪心)

题目链接

题目大意
有n个栅栏 ,其中1表示里边有牛,我们要求在原来的基础上添加两头牛之后,牛之间的最短距离。(距离为两头牛所在栅栏的坐标差)

解题思路
我们分为两种情况,在每一种情况中,头部和首部的区间进行特除计算外,中间区间的处理是一眼的。
在这里插入图片描述
情况一

  • 对于头部,最好的办法应该是将一头牛放到1位置,另一头牛放在区间内部。那么最大距离如下图。尾部的处理相同。
    在这里插入图片描述
  • 对于中间的区间,如下图
    在这里插入图片描述

情况二

  • 如果有一头牛放在首部或者尾部,那么距离就是 x 1 − 1 x1 - 1 x11 n − x m n - x_m nxm
  • 对于放入中间区间的牛,这种情况类似情况一中翻入头部的时候,是 ( x j − x i ) / 2 (x_j - x_i)/2 (xjxi)/2

综上所述,
在这里插入图片描述

解题步骤

  1. 我们将序列中,所以为1的牛的下标存入,如果一头没有就输出n - 1 即可。
  2. 之后我们求出 x m i n x_{min} xmin含义是相邻下标之差的最小值。
  3. 对于第一种情况,我们求出 三种情况,即头部,尾部和中间部分的最大值之后与 x m i n x_{min} xmin求一个min
  4. 对于情况二同理,只不过要同时维护最大值和次小值。

代码:

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 1e5 + 10 , INF = 0x3f3f3f3f;

int n;
int b[N] , cnt ;

int main(){
    cin>>n;
    char ch;
    for(int i = 1 ; i <= n ; ++i){
        cin>>ch;
        if(ch == '1') b[++cnt] = i;
    }
    if(!cnt)cout<<n-1<<endl;
    else{
        int xmin = N;
        for(int i = 1 ;i < cnt ; ++i)xmin = min(xmin , b[i+1] - b[i]);
        int y = max((b[1] - 1)/2 , (n - b[cnt]) / 2 );
        for(int i = 1 ; i < cnt ; ++i)y = max(y , (b[i+1] - b[i]) / 3 );

        int y1 = b[1] - 1 , y2 = n - b[cnt];
        if(y1 < y2)swap(y1,y2);
        for(int i = 1; i < cnt ; ++i){
            int d = (b[i+1] - b[i]) / 2;
            if(d >= y1) y2 = y1 , y1 = d;
            else if(d > y2)y2 = d;
        }
        y = min(xmin , y);
        y2 = min(xmin,y2);
        cout<<max(y2,y)<<endl;
    }
    return 0;
}

混合牛奶(模拟)

题目链接

解题思路
我们用两个数组分别存容量与当前体积。之后循环模拟即可。在模拟的时候可以利用循环和取模在优化代码。

代码:

#include<iostream>
using namespace std;
const int N = 3;
int v[N] , cur[N];

int main(){
    for(int i = 0 ; i < N  ; ++i)cin>>v[i]>>cur[i];
    
    int n = 100;
    bool flag = false;
    while(1){
        for(int i = 0 ; i < 3 ; ++i){
            int a = i , b = (i + 1) % N;
            if(cur[a] + cur[b] <= v[b]) cur[b] += cur[a] ,cur[a] = 0;
            else  cur[a] = cur[a] - (v[b] - cur[b]) ,cur[b] = v[b];
            if(--n == 0)
            {
                flag = true ;
                break;
            }
        }
        if(flag)break;
    }
    for(int i = 0 ; i < N ; ++i)cout<<cur[i]<<endl;
    return 0;
}

果壳游戏(模拟 + 技巧)

题目链接

解题思路
因为数据范围小,所有我们可以枚举石子在的位置,我们用数组来当作一个位置,里边的值是在该位置的椰子壳的编号。之后我们模拟,这里我们不用遍历石子的位置,而是用一个数组来f[i] ,表示椰子壳编号为i被点到的次数,之后取max即可。

在这里插入图片描述

代码:

#include<iostream>
#include<algorithm>
using namespace std;

const int  N = 4 , M = 110;
int A[N] ,s[N] ;

void init(){
    for(int i = 1 ; i <= N ; ++i)A[i] = i;
}


int main(){
    int n ;
    cin>>n;
    init();
    for(int j = 1 ; j <= n ; ++j){
        int a ,b,c;
        cin>>a>>b>>c;
        swap(A[a],A[b]);
        s[A[c]] ++ ;
    }
    cout<<max(s[1] , max(s[2],s[3]))<<endl;
    return 0;
}
举报

相关推荐

0 条评论