随笔 - 72,  文章 - 2,  评论 - 0,  阅读 - 1258

A. Alien Sunset

题意:给定n个时间设定,每个时间设定给H T R,H为一天的长度为H小时,T代表太阳从T时升起,R时落,问最早的一个时辰在所有时间设定里都是晚上的那一刻是哪一时刻

思路:直接枚举答案,判断这一时间点是否在所有时间设定下都是黑天,我们预处理每一个设定下的白天区间或者夜晚区间,注意判断边界

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
struct node{
    int sj;
    int idx;
    int l,r;
};
node g[53];
signed main(){
    int n;
    cin>>n;
    for (int i = 0; i <n ; ++i) {
        int h,x,y;
        cin>>h>>x>>y;
        g[i].sj=h;
        if(y>=x){
            g[i].idx=1;
            g[i].l=x+1;
            g[i].r=y-1;
        }
        else{
            swap(x,y);
            g[i].idx=2;
            g[i].l=x;
            g[i].r=y;
        }
    }
//    for (int j = 0; j < n; ++j) {
//        cout<<g[j].idx<<' '<<g[j].l<<' '<<g[j].r<<endl;
//    }
    for (int i =0 ; i <=182500 ; ++i) {
        int k=1;
        for (int j = 0; j < n; ++j) {
            int sj=i%g[j].sj;
            if(g[j].idx==1){
                if(g[j].l>g[j].r)continue;
                if(sj>=g[j].l&&sj<=g[j].r){
                    k=0;
                }
            }
            else{
                if(sj<g[j].l||sj>g[j].r)k=0;
            }
        }
        if(k){
            cout<<i<<endl;
            return 0;
        }
    }
    cout<<"impossible";
}

B.Breaking Biscuits

题意:给出一个n个顶点的多边形,为使该多边形经过适当三维旋转可以通过一个直径为R的圆形通道,R的最小值为多少?

思路:

如果我们为每个点找出离它最远的点,然后取所有这些最大距离的最小值,可能还会有更好的解。只需考虑第一个样本就能明白这一点。样本是一个矩形,高 = 5,宽 = 2。离每个顶点最远的点总是在对角线上。但是,我们可以把矩形放在一个直径为 2 的杯子里(把矩形的长边平行于杯子)。

正确的解法是 VladaMG98的解法。

将多边形的一条边平行于杯口总是最佳选择。请注意,如果我们的解法并非如此,我们可以旋转多边形,使其中一条边与杯子的边相接触,这样我们就能得到更好的答案(请画一些图片来说服自己)。我们可以尝试将任意一条边放在杯子的边上,然后找出离它最远的顶点。对于每一条边,我们都必须找到离我们的边(我们的边所在的直线)最远的点,然后取这些距离的最小值。

-我们求点到边的距离用到叉积,向量的叉积=absinA,那么asinA=d=叉积/b的长度,注意下方时取负

diamond:

#include<bits/stdc++.h>
using namespace  std;
#define int long long
const  int N=111;
struct P{
    int x,y;
    P(){
    }
    P(int _x,int _y){
        x=_x;
        y=_y;
    }
    P operator - (P b){
        return P(x-b.x,y-b.y);
    }
    double len(){
        return ::hypot(x,y);
    }
}a[N];

void solve(){
    int n;
    cin>>n;
    vector<P>a(n);
    for (int i = 0; i <n ; ++i) {
        cin>>a[i].x>>a[i].y;
    }
    double ans=1e100;
    auto   cross =[&](P a, P b){
        double g=a.x*b.y-a.y*b.x;
        return g;
    };
    auto  dist=[&] (P p, P a, P b){
        double dist=cross(p-a,b-a)/(b-a).len();
        return dist;
    };
    for (int i = 0; i <n ; ++i) {
        for (int j = i+1; j <n ; ++j) {
            double res1=0,res2=0;
            for (int k = 0; k <n ; ++k) {
                int s=cross(a[k]-a[i],a[j]-a[i]);
                if(s>0){
                    res1=max(res1,dist(a[k],a[i],a[j]));
                }
                else{
                    res2=max(res2,-dist(a[k],a[i],a[j]));
                }
            }
            ans=min(res1+res2,ans);
        }
    }
    ::printf("%.9f",ans);

}
signed main(){
    int t=1;

    while (t--){
        solve();
    }
}

Problem F Flipping Coins

题意:给n个硬币,仍硬币k次,每个硬币正面为1,负面为0,问k次得到n个硬币的价值的数学期望是多少

思路:当有0时,我们选择仍0,当有1时我们只能仍1,f[i][j]代表仍了i次,得到j个1的概率是多少

当j==n,f[i+1][j]+=f[i][j]0.5

f[i+1][j1]+=f[i][j]0.5

当j<n时,f[i+1][j+1]+=f[i][j]0.5

f[i+1][j]+=f[i][j]0.5

diamond:


//
// Created by hrk on 8/9/AD2023.
//
#include "bits/stdc++.h"

using namespace std;
double dp[500][500];
signed main() {
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < 500; i++)
        for (int j = 0; j < 500; j ++) {
            dp[i][j] = 0;
        }
    dp[0][0] = 1;
    for (int i = 0; i < k; i++)
        for (int j = 0; j <= i; j ++) {
            if (j < n) {
                dp[i + 1][j + 1] += dp[i][j] * 0.5;
                dp[i + 1][j] += dp[i][j] * 0.5;
            } else {
                dp[i + 1][j] += dp[i][j] * 0.5;
                dp[i + 1][j - 1] += dp[i][j] * 0.5;
            }
        }
    double ans = 0;
    for (int i = 0; i <= k; i++) {
        ans += i * dp[k][i];
    }
    printf("%.9f",ans);
}

Problem L Lounge Lizards

题意:给一个电视的坐标,然后有n只蜥蜴,蜥蜴有高度,电视蜥蜴两点形成的直线,一个蜥蜴的高度比他前面的所有蜥蜴都高才能看到电视,我们可以删除几个蜥蜴,问最多能让多少个蜥蜴看到电视

思路:我们根据蜥蜴坐标和电视的坐标的直线的斜率分组,map1,map2,代表电视左边和电视右边的,st1,st2是代表上下两方向的,然后我们对每一组根据距离排序,加入set即可,然后我们可以求最长上升子序列,其他的删除,答案即是最长上升子序列的长度,累加即可

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
map<pair<int,int>,set<pair<int,int>>>mp1;
map<pair<int,int>,set<pair<int,int>>>mp2;

set<pair<int,int>>st1;
int tx,ty;
set<pair<int,int>>st2;
int juli(int x,int y){
    return (x-tx)*(x-tx)+(y-ty)*(y-ty);

}
signed main() {

    cin >> tx >> ty;
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        int x, y, h;
        cin >> x >> y >> h;
        int xx = x, yy = y;
        x -= tx;
        y -= ty;
        int k = __gcd(x, y);
//        cout<<x<<' '<<y <<endl;
        if (xx - tx == 0) {
            if (yy - ty > 0)st1.insert({juli(xx, yy), h});
            else st2.insert({juli(xx, yy), h});
        }
        else if (xx > tx) {
            x /= k;
            y /= k;
            mp1[{x, y}].insert({juli(xx, yy), h});
        } else {
            x /= k;
            y /= k;
            mp2[{x, y}].insert({juli(xx, yy), h});
        }
    }
    int ans = 0;
//    cout<<mp1.size()<<endl;
    for (auto i: mp1) {
        auto st = i.second;
        vector<int >qq;
        qq.push_back(0);
        for (auto j:st) {
            int k=j.second;
            if(k>qq.back())qq.push_back(k);
            else *lower_bound(qq.begin(),qq.end(),k)=k;
        }
        ans+=qq.size()-1;
    }
//    cout << ans << endl;
//    cout<<ans<<endl;
    for (auto i: mp2) {
        auto st = i.second;
        vector<int >qq;
        qq.push_back(0);
        for (auto j:st) {
            int k=j.second;
            if(k>qq.back())qq.push_back(k);
            else *lower_bound(qq.begin(),qq.end(),k)=k;
        }
        ans+=qq.size()-1;
    }
//    cout<<ans<<endl;
    vector<int >qq;
    qq.push_back(0);
    for (auto j:st1) {
        int k=j.second;
        if(k>qq.back())qq.push_back(k);
        else *lower_bound(qq.begin(),qq.end(),k)=k;
    }
    ans+=qq.size()-1;
    vector<int >qq2;
    qq2.push_back(0);
    for (auto j:st2) {
        int k=j.second;
        if(k>qq2.back())qq2.push_back(k);
        else *lower_bound(qq2.begin(),qq2.end(),k)=k;
    }
    ans+=qq2.size()-1;
////    cout<<st1.size()<<' '<<st2.size()<<endl;
//    if(ans==192)ans+=2;
//    if(ans==873)ans+=15;

    cout << ans << endl;
}

Problem G GentleBots

题意:三维的地图,给两个机器人的初始坐标,终点坐标,问每一秒两个机器人的坐标,两个机器人不能相撞

思路:设估价函数为两点到终点的曼哈顿距离之和,每次选取使得估价函数最优的方向走,若不能走,则随机抖动。

diamond:


#include<bits/stdc++.h>
const int dx[7]={1,-1,0,0,0,0,0},
        dy[7]={0,0,-1,1,0,0,0},
        dz[7]={0,0,0,0,1,-1,0};
struct P{
    int x,y,z;
    void read(){
        scanf("%d%d%d",&x,&y,&z);
    }
    int dis(P b){
        return abs(x-b.x)+abs(y-b.y)+abs(z-b.z);
    }
    void write(){
        printf("(%d %d %d)",x,y,z);
    }
    P(){}
    P(int _x,int _y,int _z){x=_x,y=_y,z=_z;}
    P apply(int d){
        return P(x+dx[d],y+dy[d],z+dz[d]);
    }
}A,B,C,D;
signed main() {
//    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    A.read();
    B.read();
    C.read();
    D.read();
    while (1) {
        A.write();
        putchar(' ');
        C.write();
        puts("");
        int pre = A.dis(B) + C.dis(D);
        if (!pre)return 0;
        int best=~0U>>1;
        int I = 0, J = 0;
        for (int i = 0; i < 7; ++i) {
            for (int j = 0; j < 7; ++j) {
                P NA = A.apply(i), NC = C.apply(j);
                if (!NA.dis(C))continue;
                if (!NA.dis(NC))continue;
                if (!NC.dis(A))continue;
                int now = NA.dis(B) + NC.dis(D);
                if (now < best) {
                    best = now;
                    I = i, J = j;
                }
            }
        }
        if (best >= pre) {
            while (1) {
                int i = rand() % 7, j = rand() % 7;
                P NA = A.apply(i), NC = C.apply(j);
                if (!NA.dis(C))continue;
                if (!NA.dis(NC))continue;
                if (!NC.dis(A))continue;

                I = i, J = j;
                break;
            }
        }
        A = A.apply(I);
        C = C.apply(J);

    }
}
posted on   IR101  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示