CCPC-Wannafly Summer Camp 2019 Day5

本文总结了CCPC Wannafly Summer Camp 2019第五天的竞赛题目,包括Alice's Print Service的动态规划解法,Collision的几何碰撞问题,以及Josephina and RPG的博弈论思路。通过对这些题目深入剖析,展示了参赛者对算法的理解和应用能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Day5 题目做完,感觉银牌距离我近而遥远…

这套题五题稳银,而且这五题都不算难题,但是看看自己能不能一遍写成,这是有难度的…

A.Alice’s Print Service

买东西,买的越多越便宜,每次询问一个x,求买x件物品最便宜的价格(可以多买)
维护一个区间最小值 M I N i 表 示 i − n 的 区 间 最 小 值 MIN_i表示i-n的区间最小值 MINiin,我们知道,我们可以多买,但是不能少买.设小于当前数量的标准为i,所以只需要比较 min ⁡ i + 1 n M I N i \min\limits_{i+1}^{n} MIN_i i+1minnMINi ( x − s [ i ] ) ∗ p [ i ] (x-s[i])*p[i] (xs[i])p[i],取较小的即可(查找i要用二分)
(其实这题开始想线段树RMQ的…)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
ll jt[maxn],pri[maxn];
ll minn[maxn];
int n,m;
ll mymin(ll a,ll b){
    return a<b?a:b;
}
int main()
{
    int t;scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%lld%lld",&jt[i],&pri[i]);
        }
        ll mint=1e18+18;
        for(int i=n;i>=1;--i) {
            mint=mymin(mint,jt[i]*pri[i]);
            minn[i]=mint;
        }
        minn[n+1]=1e18+18;
        for(int i=1;i<=m;++i){
            ll t;
            scanf("%lld",&t);
            int pos=upper_bound(jt+1,jt+1+n,t)-jt;
            //cout<<pos<<endl;
            printf("%lld\n",mymin(minn[pos],t*pri[pos-1]));
        }
    }
}

C.Collision

####简单几何

有一个奖章,半径为 R m R_m Rm,一个圆圈,半径为R,一个硬币,半径为r,其中奖章和圆圈是同心圆,圆心为(0,0),给定硬币的坐标 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)和初始x,y速度x,y,求硬币在圆圈内的时间(若和奖章发生碰撞,按弹性碰撞处理,速度不变)

先讨论下硬币会不会进入圆圈,不会就输出0.条件:
(1) ( x 0 ⃗ , y 0 ⃗ ) ⋅ ( x ⃗ , y ⃗ ) ≥ 0 (\vec{x_0},\vec{y_0})\cdot(\vec{x},\vec{y})\geq0 (x0 ,y0 )(x ,y )0
(2)与圆心距离大于 ( R m + r ) (R_m+r) (Rm+r)
其余写在注释

#include<bits/stdc++.h>
using namespace std;

double Rm,R,r,a,b,x0,y_;
void solve()
{
    double v=a*a+b*b;v=sqrt(v);
    double d,k;
    double time;
    if(a==0){
        d=abs(x0);//别忘了绝对值,开始就wa在了这里
    }
    else {
        double k=b/a;
        double b0=y_-k*x0;
        d=abs(b0/sqrt(k*k+1));//绝对值
    }
    if(d>R+r || a*x0+y_*b>=0){
        printf("%.3f\n",0.0000);
        return;
    }else{
        double q=(R+r)*(R+r)-d*d;q=sqrt(q);
        if(d<Rm+r){
            double q2=(Rm+r)*(Rm+r)-d*d;
            q2=sqrt(q2);
            double l=q-q2;
            time=l*2/v;//碰撞后直接时间*2
        }else{
            time=q*2/v;//接触圆环的时间到经过垂直于轨迹的过原点的直线的时间*2
        }
    }
    printf("%.3f\n",time);
}
int main()
{
    while(cin>>Rm>>R>>r>>x0>>y_>>a>>b){
        solve();
    }
}

##H.Skycity
开始读错题…
####给建筑铺玻璃,问最少要多少玻璃,建筑是图中的一个个圆柱,玻璃是外面的切面.求玻璃最小面积是,(每块玻璃最小值是S(因为高度一定,所以相当于玻璃最小长度固定))
其实挺水的一道题,直接上代码

#include<bits/stdc++.h>
using namespace std;
double R,r,H,n,S;
double Ra[1200];
const double PI=acos(-1);
void solve(){
    memset(Ra,0,sizeof(Ra));
    for(int i=1;i<=n;++i){
        Ra[i]=r+(R-r)/n*(i-1);根据样例,并没有包括最下面面积为R的一层
        //cout<<Ra[i]<<" ";
    }
    double d=S*n/H/2;
    double h=H/n;
    double ans=0;
    for(int i=1;i<=n;++i){
        int x=PI/atan(d/Ra[i]);
        ans+=2*h*x*Ra[i]*tan(PI/x);
    }
    printf("%.4f\n",ans);
}
int main()
{
    //freopen("in","r",stdin);
    while(cin>>R>>r>>H>>n>>S){
        solve();
    }
}

J.Josephina and RPG

这题还是比较简单的,就是题面有点长,dp一下就ok.注意输入的矩形边长是 C n 3 C_n^3 Cn3,不是n,
还有注意对于一个敌人,他的编号是 I D [ i ] , 不 是 i ID[i],不是i ID[i],i

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+4;
double dp[130][maxn],P[130][130];
int ai[maxn];
int main()
{
    int n;
    while(cin>>n){
        n=n*(n-1)*(n-2)/6;
        memset(dp,0,sizeof(dp));
        memset(P,0,sizeof(P));
        memset(ai,0,sizeof(ai));
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            cin>>P[i][j];
        }
    }
    int N;cin>>N;
    for(int i=0;i<130;++i) dp[i][0]=1;
    for(int i=1;i<=N;++i) cin>>ai[i],++ai[i];
    for(int j=0;j<N;++j){
        for(int i=1;i<=n;++i){
            dp[i][j+1]=max(dp[i][j+1],dp[i][j]*P[i][ai[j+1]]);//不交换
            if(j>0)
            dp[ai[j]][j+1]=max(dp[ai[j]][j+1],dp[i][j]*P[ai[j]][ai[j+1]]);//交换
        }
    }
    double ans=0;
    for(int i=1;i<=n;++i) ans=max(ans,dp[i][N]);
    printf("%.7f\n",ans);
    }
}

##K.Pocket Cube
####…魔方题,不多说了,细心就好(前面的省略号表示无语,无奈)
因为每次可以走6步,最多走7次, 6 7 = 279936 6^7=279936 67=279936,甚至不必判重,直接暴力dfs就好

#include<bits/stdc++.h>
using namespace std;
int n;
int a[24];
int T[6][24]={
        {0,21,2,23,4,5,6,1,9,15,10,11,12,3,8,14,16,7,18,13,20,17,22,19},
        {0,7,2,13,4,5,6,17,14,8,10,11,12,19,15,9,16,21,18,23,20,1,22,3},
        {0,1,2,3,4,5,6,7,8,9,12,13,14,15,21,20,17,19,16,18,11,10,22,23},
        {0,1,2,3,4,5,6,7,8,9,21,20,10,11,12,13,18,16,19,17,15,14,22,23},
        {0,1,11,5,4,16,12,6,2,9,10,17,13,7,3,15,14,8,18,19,20,21,22,23},
        {0,1,8,14,4,3,7,13,17,9,10,2,6,12,16,15,5,11,18,19,20,21,22,23}
};
int count(int t[24]){
     int res=0;
    if (t[0]==t[1] && t[1]==t[2] && t[2]==t[3]) res++;
    if (t[8]==t[9] && t[14]==t[15] && t[8]==t[14]) res++;
    if (t[6]==t[7] && t[7]==t[12] && t[12]==t[13]) res++;
    if (t[4]==t[5] && t[5]==t[11] && t[11]==t[10]) res++;
    if (t[16]==t[17] && t[17]==t[19] && t[19]==t[18]) res++;
    if (t[20]==t[21] && t[21]==t[22] && t[22]==t[23]) res++;
    return res;
}
int ans;
int cnt=0;
void dfs(int t[24],int step){
    ans=max(ans,count(t));
    if(step==n) return;
    int tt[24];
    for(int i=0;i<6;++i){
        for(int j=0;j<24;++j){
            tt[j]=t[T[i][j]];
        }
        dfs(tt,step+1);
    }
}
int main()
{
    //freopen("in","r",stdin);
    while(cin>>n){
        for(int i=0;i<24;++i) cin>>a[i];
        ans=0;
        dfs(a,0);
        cout<<ans<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值