春季每日一题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 x1−1 和 n − x m n - x_m n−xm
- 对于放入中间区间的牛,这种情况类似情况一中翻入头部的时候,是 ( x j − x i ) / 2 (x_j - x_i)/2 (xj−xi)/2
综上所述,
解题步骤
- 我们将序列中,所以为1的牛的下标存入,如果一头没有就输出n - 1 即可。
- 之后我们求出 x m i n x_{min} xmin含义是相邻下标之差的最小值。
- 对于第一种情况,我们求出 三种情况,即头部,尾部和中间部分的最大值之后与 x m i n x_{min} xmin求一个min
- 对于情况二同理,只不过要同时维护最大值和次小值。
代码:
#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;
}