TJUACM春季集训 个人赛03 部分题解

TJUACM春季集训 个人赛03icon-default.png?t=N7T8https://acm.tju.edu.cn/contest/1056这次个人赛总的来说做题感觉还好,题目难度比较简单,感觉题目描述的都很直接,大部分都是模拟题,基本没有用到算法,思路也比较清晰,前一个半小时做了六道题,但是AC的只有三道,后面的大部分时间都在反复检查那三道题,好在最后都过了,剩下的一点点时间用在了把其余题目都简单过了一遍,看到榜单上没有几个做出来的,最后也摆了一会儿,总体上这次比赛给自己评分良好。

下面主要写一下我今天AC的六道题,其余的题目后面再补吧(大概率不会再补了2333)

A.Supermarket

题意:

题目给出了多个超市卖的价格,以a yuan for b kilos的形式给出,求给定kilo的最小花费

思路:

这道题主要思路是定义一个结构体数组来存储各个supermarket的价格,然后循环找到最小单价,输出最小单价乘以数量就是最终1的最小花费了,其实最主要的事注意一些细节,比如浮点数运算的时候小心整数溢出。

AC代码如下: 

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

struct market{
    int yuan;
    int kilo;
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    
    int n,m;
    cin>>n>>m;
    market mar[n+1];
    for(int i=1;i<=n;i++) cin>>mar[i].yuan>>mar[i].kilo;
    double mini=0x3f3f3f;
    for(int i=1;i<=n;i++){
        double sin=1.0*mar[i].yuan/mar[i].kilo;
        mini=min(mini,sin);
    }
    
    cout<<fixed<<setprecision(8)<<1.0*m*mini<<endl;

    return 0;
}

B.Perfect Number

题意:

求第k个所有数位上和是10的数

思路:

这道题看起来比较吓人,乍一看好像是找规律的题目,但是我似乎并没有找到规律,于是就换个思路想会不会是暴力,看到k的范围最大是10000,写了几个数,感觉还是挺密集的,可以一试,于是就直接从头遍历所有数判断是否符合perfect,直到找到第k个数为止就好了。

AC代码如下:

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

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    int k;
    cin>>k;
    int count=0,i=0;
    while(count<k&&++i){
        int sum=0,temp=i;
        while(temp){
            sum+=temp%10;
            temp/=10;
        }
        if(sum==10) count++;
    }
    cout<<i<<endl;

    return 0;
}

C.Seat Arrangement

题意:

以字符矩阵的形式给出空闲和不空闲的位置,判断横或者竖着的连续k个空闲座位有几种

思路:

这道题就简单的横着和竖着分别数有每行或者每列有几个连续的座位就好了,但是但是但是!!!如果暴力地判断的话,每种判断里面用到了三个循环,复杂度为O(n的3次方),看一下数据范围为2000,有可能超了,也确实,我刚开始没有主要到,TLE了。之后修改的时候,想到不能简单暴力,用到一点比较巧妙,如果有多余k的连续的temp个空闲座位,这里就不用遍历多次了,就直接增加temp-k+1种方案就好了,可以跳过不少的情况,而且k越大,跳过的越多,这就是相当于制约了k,不用怕极端的数据k=2000了。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2024;
int arr[maxn][maxn];
int n,m,k;
long long ans=0;

void init(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            char ch;
            cin>>ch;
            if(ch=='.') arr[i][j]=1;
            else if(ch=='*') arr[i][j]=0;
        }
    }
}

void check_row(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(arr[i][j]==1){
                int r=j+1;
                int temp=1;
                while(arr[i][r]==1){
                    r++;
                    temp++;
                }
                ans+=max(0,temp-k+1);
                j=r-1;
            }
        }
    }
}

void check_col(){
    for(int j=1;j<=m;j++){
        for(int i=1;i<=n;i++){
            if(arr[i][j]==1){
                int r=i+1;
                int temp=1;
                while(arr[r][j]==1){
                    r++;
                    temp++;
                }
                ans+=max(0,temp-k+1);
                i=r-1;
            }
        }
    }
}

void special_judge(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            ans+=arr[i][j];
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    cin>>n>>m>>k;
    init();
    if(k==1){
        special_judge();
    }
    else{
        check_row();
        check_col();        
    }
    cout<<ans<<endl;

    return 0;
}

F.Watering The Garden

题意:

有一排n块土壤,给出了k个浇水点,每个浇水点每秒向左右个移动一块土壤,求完全浇完水的时间

思路:

这道题主要用到贪心的想法,其实完全浇完水的时间就是最长的那一个,而最长的那一个是距离浇水点最远的那个,只有三种可能,最左边的浇水点到一个块土、最右边的浇水点到最后一块土、两个浇水点之间的最远的土,这三种可能取最大值就好了。

AC代码如下:

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

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    
    int t;
    cin>>t;
    while(t--){
        int n,k;
        cin>>n>>k;
        int arr[k+1];
        for(int i=1;i<=k;i++){
            cin>>arr[i];
        }
        int len=-0x3f3f3f;
        for(int i=1;i<=k-1;i++){
            len=max(len,arr[i+1]-arr[i]);
        }
        sort(arr+1,arr+k+1);
        int l1=arr[1]-1,l2=n-arr[k];
        int res=max({l1+1,l2+1,len/2+1});
        cout<<res<<endl;
    }

    return 0;
}

G.Tea Queue

题意:n个人排队取茶,给出每个人的取茶时间和最晚取茶时间,按取茶时间取茶,前面如果有人则需要等候,每个人取茶需要一秒,如果超过最晚取茶时间则踢出队伍,求每个人的实际取茶时间

思路:

简单的定义一个结构体数组模拟一下就好了,需要注意的是,如果没到自己的取茶时间而前面没有人了,需要等候,我交的时候一直没意识到这个问题,WA了好几次。

AC代码如下:

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

struct person{
    int l;
    int r;
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        person p[n+1];
        for(int i=1;i<=n;i++) cin>>p[i].l>>p[i].r;
        int second=1;
        for(int i=1;i<=n;i++){
            if(p[i].l>second) second=p[i].l;
            if(p[i].r>=second){
                cout<<second;
                second++;
            }
            else cout<<"0";
            if(i!=n) cout<<" ";
        }
        cout<<endl;
    }

    return 0;
}

H.Swap Adjacent Elements

题意:

给定一条数列,1-n个出现一次,并给定一个字符串,其中用0和1表示对应数列中的数可不可以和后面相邻的数交换。判断该数列能否在此限制中交换为非降序数列。

思路:

正向遍历,只要当前的最大数比位数i大,说明要向后移动,再判断如果当前对应的string表示为0,则一定不能交换得到;

AC代码如下:

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

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    
    int n;
    cin>>n;
    int arr[n+1];
    for(int i=1;i<=n;i++){
        cin>>arr[i];
    }
    string s;
    cin>>s;
    
    bool res=1;
    int maxn=0;
    for(int i=1;i<=n;i++){
        maxn=max(maxn,arr[i]);
        if(s[i-1]=='0'&&maxn>i){
            res=0;
            break;
        }
    }

    if(res) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;

    return 0;
}

其他的题有缘再见吧2333

  • 34
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值