upc个人训练赛第05场

目录

A:智力测试题

题意:

思路:

代码:

B:采集灵石

题意:

思路:

代码:

C: 跳跃的排列

题意:

思路:

代码:

I: Four Points

题意:

思路:

代码:

J: Get Closer

题意:

思路:

代码:

K: Coupon

题意:

思路:

代码:

R: Watering the Fields

题意:

思路:

代码:


A:智力测试题

题意:

已知一个n乘以n的矩阵,有一个小球一开始在(1,1)处,小球每秒都会向右走一格,如果到达最右边,小球就会掉落在下一行的第一格。
如果到达(n, n)则返回(1,1)。现在给定n和时间t,请你输出小球最后所在的行和列。

思路:

模拟下落过程,对时间取余,注意到达n,n时的处理

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{   int n,t;
    cin>>n>>t;
     if((t/n+1)%n==0) 
     cout<<n<<" "<<t%n+1;
     else cout<<(t/n+1)%n<<" "<<t%n+1;
}

B:采集灵石

题意:

灵石会在许多浮岛上刷新,每个浮岛上灵石刷新数量可能不同。这些浮岛之间通过传送法阵相连,激活每个岛屿上的传送法阵花费的灵石数量也不同。玩家可以耗费mi 块灵石从任意一个其他浮岛或初始平台前往第i个浮岛。采集完毕后玩家可以从任何浮岛直接退出地图。

现在,牛牛手中有着K块灵石,他想知道自己今天采集结束后最多能拥有多少块灵石。

思路:

根据实际可得的灵石数维持单调队列,每次访问队首元素,若当前灵石够传送所消耗的,则得到该出灵石差值,并出队;若不够消耗,则出队暂时储存,继续判断下一个,直到再次取灵石时入队。

代码:

#include <iostream>
#include <queue>
using namespace std;
 
typedef pair<int,int> PII;
const int M = 100010;
 
priority_queue<PII, vector<PII>, greater<PII> > q;
int f[M];//只去前i个岛上可取的最大值
 
int main()
{
    int n, k;
    cin >> n >> k;
    f[0] = k;
 
     
    for(int i=0 ; i<n ; i++)
    {
        int w, v;
        cin >> w >> v;
        if(w>v)
            q.push( {v, w-v} );
    }
 
    long long res = k;
     
    while(!q.empty())
    {
        PII t = q.top();
        q.pop();
         
        if(res >= t.first)
            res += t.second;
    }
     
    cout << res;
 
    return 0;
}

C: 跳跃的排列

题意:

小 B 很喜欢排列,这次他有一个长为n的排列 a1, a2, ⋯ , an。由于他音游玩多了,所以他想让排列也跳跃起来。他定义一次排列的跳跃为:

令 bi 表示最大的j (i ≤ j ≤ n)满足 aj ≥ ai,则bi= aj。最后对于所有i = 1 ∼ n,将 ai赋值为bi。  

他想重复上述操作若干次。若操作k次和操作k + 1次序列保持不变,那么跳跃停止,跳跃次数为k。他想知道排列会跳跃多少次,请你来帮他计算一下。 

思路:

经过推导,跳跃次数非0即1,则只需判断最后一个数之前是否有比他小的。

因此只要维护一个前n项最小值数组判断即可。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,p,a[1000100],b[1000100];
int main()
{  
   cin>>n;
   for(int i=1;i<=n;i++)
     cin>>a[i];
    b[1]=a[1];
   for(int i=2;i<=n;i++)
     { if(b[i-1]>=a[i]) b[i]=a[i];
       else b[i]=b[i-1];
     }
   if(a[n]<=b[n]) cout<<"0";
   else cout<<"1";
}

I: Four Points

题意:

给出平行轴的矩形的三个坐标,写出其第四个坐标值。

思路:

分情况讨论第四个点的位置。

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{   int x1,x2,x3,y1,y2,y3;
    cin>>x1>>y1;
    cin>>x2>>y2;
    cin>>x3>>y3;
    if(x1==x2)
    { if(y1==y3) cout<<x3<<" "<<y2;
      else if(y2==y3) cout<<x3<<" "<<y1;
    }
    else if(x1==x3)
    { if(y1==y2) cout<<x2<<" "<<y3;
      else if(y2==y3) cout<<x2<<" "<<y1;
    }
    else if(x2==x3)
    { if(y1==y2) cout<<x1<<" "<<y3;
      else if(y1==y3) cout<<x1<<" "<<y2;
    }
}

J: Get Closer

题意:

给出直角三角形的两直角边,问其缩小到斜边为1时的两直角边的值。

思路:

先算出当前斜边值,再用当前直角边除以该值。

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{  double a,b;
   cin>>a>>b;
   if(a==0) cout<<0<<" "<<1;
   else if(b==0) cout<<1<<" "<<0;
   else
    cout<<a/sqrt(a*a+b*b)<<" "<<b/sqrt(a*a+b*b);
}

K: Coupon

题意:

商店里有N件商品。高桥有K优惠券。每张优惠券可用于一件商品。您可以在同一商品上使用任意数量的优惠券,可能为零。使用k优惠券可以让您以max{a−kX,0}日元的价格购买。打印高桥购买所有物品所需的最低金额。

思路:

先算出每件商品最多恰好用完的优惠劵数目,若优惠券不够,直接计算;否则用剩下的券优先给零头大的商品使用,剩下的商品零头总和即为最低金额。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,x,a[1000100],ans=0,sum=0,pt=0,kk;
int main()
{  cin>>n>>k>>x;
   for(int i=1;i<=n;i++)
      cin>>a[i];
   for(int i=1;i<=n;i++)
      { if(sum<k)
       {sum+=a[i]/x;
        a[i]=a[i]%x;
       }
       else
       { pt=1;kk=i;
         break;
       }
     }
   if(pt==1)
   { a[kk]=a[kk]+x*(sum-k);
     for(int i=1;i<=n;i++)
       ans+=a[i];
     cout<<ans;
   }
   else
   { sort(a+1,a+1+n,greater<int>());
    for(int i=k-sum+1;i<=n;i++)
      ans+=a[i];
    cout<<ans;
   }
}

R: Watering the Fields

题意:

FJ 希望建立一个最低成本的管道系统,以便他的所有油田都平整在一起 - 这样任何田地中的水都可以沿着管道序列到达任何其他场。

思路:

最小生成树模板题。

代码:

#include <bits/stdc++.h>
#define ri register int 
#define ll long long 
using namespace std;
const int maxn=2005;
const int inf=192681792;
struct Edge{
int u,v,dis;
bool operator <(const Edge& b)const{
    return dis<b.dis;
}
}edge[100000010];
int n,c,tot=0;
int px[maxn],py[maxn];
int fa[maxn];
int get(int x){
if(fa[x]!=x)fa[x]=get(fa[x]);
return fa[x];
}
inline void kruskal(){
int u,v,dis;
int cnt=0,ans=0;
for(ri i=1;i<=n;i++){
    fa[i]=i;
}
for(ri i=1;i<=tot;i++){
    u=edge[i].u,v=edge[i].v;
    u=get(u),v=get(v);
    if(u!=v){
        fa[u]=v;
        ans+=edge[i].dis;
        cnt++;
    }
    if(cnt==n-1)break;
}
if(cnt==n-1)printf("%d",ans);
else puts("-1");
return ;
}
int main(){
scanf("%d %d",&n,&c);
for(ri i=1;i<=n;i++){
    scanf("%d %d",&px[i],&py[i]);
    for(ri j=1;j<i;j++){
        int d=(px[i]-px[j])*(px[i]-px[j])+(py[i]-py[j])*(py[i]-py[j]);
        if(d>=c){
            edge[++tot].u=i,edge[tot].v=j,edge[tot].dis=d;
        }
    }
}
sort(edge+1,edge+1+tot);
kruskal();
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亦木不emo

打赏一个吧亲

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值