赛码解题报告(四)

聊天

题目描述

小明和小红是身处异地的好朋友,两人经常在空闲时间进行网上聊天。两个人空闲时间都是安排好的,小明的时间表是固定的,是[a1, b1], [a2, b2], …, [ap, bp];而小红的时间表比较怪,是依赖她起床时间t的,是[c1+t, d1+t], [c2+t, d2+t], …, [cq+t, dq+t];值得注意的是,两个人时间表上的边界点也是空闲时间。小红起床时间t为[l, r]之间的任意一个整点时刻(也包括边界),只要两人能在任一时刻同时在线进行聊天,那么t就是小红合适的起床时间。询问小红能够有多少个合适的起床时间?

输入

第一行数据四个整数:p,  q,  l,  r (1≤  p, q≤50, 0≤l ≤r≤1000)。接下来p行数据每一行有一对整数ai, bi (0≤ ai<bi≤ 1000)表示小明的时间表,在接下来q行数据每一行有一对整数ci, di="" (0≤ cibi, cj+1>dj。</bi≤ 1000)表示小明的时间表,在接下来q行数据每一行有一对整数ci,>


样例输入

2 3 0 20

15 17

23 26

1 4

7 11

15 17


输出

输出能够进行聊天的合适的起床时间点的个数。


样例输出

2


本题只需对区间内的每个t进行尝试即可,但要注意两个区间不相交的条件~

#include<stdio.h>
struct Time{
    int a;
    int b;
};
int p,q,l,r;
bool pa(int a,int b,int c,int d){
        if(!((d<a||c>b)||(b<c||a>d)))
        //if(c<=a&&d>=a&&d<=b||c>=a&&d<=b||c<=b&&c>=a&&d>=b)
            return true;
        else return false;
}
bool judgement(Time a[],Time b[]){
    for(int i=0;i<p;i++){
        for(int j=0;j<q;j++){
            if(pa(a[i].a,a[i].b,b[j].a,b[j].b))
                return true;
        }
    }
    return false;
}


int main(){


    Time m[50];
    Time h[50];
    scanf("%d %d %d %d",&p,&q,&l,&r);
    for(int i=0;i<p;i++){
        scanf("%d %d",&m[i].a,&m[i].b);
    }
    for(int i=0;i<q;i++){
        scanf("%d %d",&h[i].a,&h[i].b);
    }
    int countx=0;
    Time yuanshi[50];
    for(int k=l;k<=r;k++){
        for(int i=0;i<q;i++){
            yuanshi[i].a=h[i].a+k;
            yuanshi[i].b=h[i].b+k;
        }
        if(judgement(m,yuanshi)){
           countx++;
        }
    }
        printf("%d\n",countx);
     return 0;
}


击鼓传花

题目描述

学校联欢晚会的时候,为了使每一个同学都能参与进来,主持人常常会带着同学们玩击鼓传花的游戏。游戏规则是这样的:n个同学坐着围成一个圆圈,指定一个同学手里拿着一束花,主持人在旁边背对着大家开始击鼓,鼓声开始之后拿着花的同学开始传花,每个同学都可以把花传给自己左右的两个同学中的一个(左右任意),当主持人停止击鼓时,传花停止,此时,正拿着花没传出去的那个同学就要给大家表演一个节目。
聪明的小赛提出一个有趣的问题:有多少种不同的方法可以使得从小赛手里开始传的花,传了m次以后,又回到小赛手里。对于传递的方法当且仅当这两种方法中,接到花的同学按接球顺序组成的序列是不同的,才视作两种传花的方法不同。比如有3个同学1号、2号、3号,并假设小赛为1号,花传了3次回到小赛手里的方式有1->2->3->1和1->3->2->1,共2种。

输入

输入共一行,有两个用空格隔开的整数n,m(3<=n<=30,1<=m<=30)

样例输入

3 3


输出

输出共一行,有一个整数,表示符合题意的方法数

样例输出

2

本题实质为动规问题。对于两头的1和n来说,其传花种类分别等于n和2.n-1和1;

对于中间的点则取决与旁边两个点。

对于dp[0][1]:代表0步到达1.也可以理解为从1 开始,所以=1;

dp[1][n]=1;

dp[1][2]=1;//均为1传给旁边两个点的。

代码如下

#include<stdio.h>
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    int dp[35][35];
    dp[0][1]=1;
    dp[1][n]=1;
    dp[1][2]=1;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            if(j==1)
                dp[i][j]=dp[i-1][2]+dp[i-1][n];
            else if(j==n)
                dp[i][j]=dp[i-1][n-1]+dp[i-1][1];
            else dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1];
        }
    }
    printf("%d\n",dp[m][1]);
    return 0;
}



喷水装置

题目描述

小赛家有一块草坪,长为20米,宽为2米,妈妈要他给草坪浇水,在草坪上放置半径为Ri的喷水装置,每个喷水装置可以给以它为中心的半径为实数Ri(1<Ri<15)的圆形区域浇水。他家有充足的喷水装置i(1<i<600)个,并且一定能把草坪全部湿润。你能帮他计算一下,把整个草坪全部湿润,最少需要几个喷水装置。

输入

输入第一个数字为喷水装置的个数n,后面n个数字分别为n个喷水装置的半径r,r表示该喷水装置能覆盖的圆的半径。

喷水装置i的范围为:1<i<600,半径的范围为:1<Ri<15。

样例输入

5

2 3.2 4 4.5 6

输出

输出所用装置的个数。

样例输出

2

选择语言:
请选择语言
1
本题着实是有一些坑,要注意好数学问题,圆形覆盖长方形结果为正方形,链接见——http://zhidao.baidu.com/link?url=AU22bRurjBRytLhma3oJwS6rOnhzXJxFm7jrohP5pQxrhE371-W1Lv3AnCejJtYEvIp0XsbcpxrNxwG9ta_mPpOdQyXPH48hG67GqDCHsJ_

所以每次减去的为sqrt(r*r-1)*2;还要注意double为ld输入

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int cmp(const void *a,const void *b){
    if(*(double*)a>*(double *)b)
        return 1;
    else return -1;
}
int main(){
    int n;
    double r[600];
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%lf",&r[i]);
    qsort(r,n,sizeof(double),cmp);
    double current=0;
    int indexx=0;
    for(int i=n-1;i>=0;i--){
        if(current>=20){
            break;
        }
        else {


            current+=sqrt(r[i]*r[i]-1)*2;
            indexx++;


        }
    }
    printf("%d\n",indexx);
    return 0;
}

三分线

题目描述

小赛很喜欢看A队和B队的篮球比赛。众所周知,篮球每回合根据投篮远近可以得2分或3分。如果投篮距离小于d那么得2分,大于等于d得3分。我们将d记为三分线。


每次小赛都喜欢通过改变三分线的大小来让自己支持的A队获取更大的优势。现给出两个队伍投篮得分的距离,小赛希望你能够帮他选择一个合理的三分线,使得A队优势最大。


输入

输入数据包含两行。

第一行第一个数为n(1≤n≤2*105), 表示A队进球数,接下来n个正整数表示A队每次进球的投篮位置ai(1≤ai≤2*109)。 

第二行第一个数为m(1≤m≤2*105),表示B队进球数,接下来m个正整数表示B队每次进球的投篮位置bi(1≤bi≤2*109)。


样例输入

3 1 2 3

2 5 6

输出

一个整数,表示A队得分减去B队得分的最大值 

样例输出

3

本题比较复杂,首先对于a中的距离和d中的距离排序,再分别按次序从第一个为2分球其余为三分球开始计算,类似于归并排序???

然后对于边界上的点再进行处理。


#include <stdio.h>
#include <vector>
#include <algorithm>
#include <limits.h>


using namespace std;


int max(int a, int b)
{
return a>b?a:b;
}


int getScore(int index_minScore3, int n)
{//逐个试探d
return index_minScore3*2 + (n-index_minScore3)*3;
}


int getV(vector<int> vec_1, vector<int> vec_2)
{
sort(vec_1.begin(), vec_1.end());
sort(vec_2.begin(), vec_2.end());


int maxScore = -INT_MAX;
int i=0,j=0;
while(i<vec_1.size() && j<vec_2.size()){
maxScore = max(maxScore, getScore(i,vec_1.size())-getScore(j,vec_2.size()));
//移动过后继续比较
if(vec_1[i] < vec_2[j]){
i++;
}else if(vec_1[i] > vec_2[j]){
j++;
}else{
i++;
j++;
}
}


if(i==vec_1.size() && j==vec_2.size())
maxScore = max(maxScore, getScore(i,vec_1.size())-getScore(j,vec_2.size()));


if(i<vec_1.size() && j==vec_2.size())
maxScore = max(maxScore, getScore(i,vec_1.size())-getScore(j,vec_2.size()));


if(i==vec_1.size() && j<vec_2.size())
maxScore = max(maxScore, getScore(i,vec_1.size())-getScore(vec_2.size(),vec_2.size()));


return maxScore;
}


int main()
{
int n,m;


scanf("%d", &n);
vector<int> vec_1;
vec_1.resize(n);
for(int i=0;i<n;i++){
scanf("%d", &vec_1[i]);
}




scanf("%d", &m);
vector<int> vec_2;
vec_2.resize(m);
for(int i=0;i<m;i++){
scanf("%d", &vec_2[i]);
}


int res = getV(vec_1, vec_2);
printf("%d\n", res);


return 0;
}



字符判断

题目描述

判断字符串b的所有字符是否都在字符串a中出现过,a、b都是可能包含汉字的字符串。b中重复出现的汉字,那么a中也要至少重复相同的次数。汉字使用gbk编码(简单的说,用两个字节表示一个汉字,高字节最高位为1的代表汉字,低字节最高位可以不为1)。

        int is_include(char *a, char *b); 

     返回0表示没有都出现过,返回1表示都出现过。 

请设计一个算法。


输入

从标准输入中读取输入内容,文件中的内容如下

字符串a\n字符串b


样例输入

aaaabbbcccdddss

abc


输出

标准输出中输出0或者1


样例输出

1

本题直接逐个判断即可,注意用map之后可以使其更加简单~

#include<stdio.h>
#include<iostream>
#include <string.h>
#include <string>
#include <map>
using namespace std;


bool is_include(char *s1,char *s2)
{
int t1 = strlen(s1);
int t2 = strlen(s2);


map<char,int> m;
for (int i = 0; i < t1; i++)
{
if (m.find(s1[i]) == m.end())
m[s1[i]] = 1;
else
m[s1[i]]++;
}


for (int j = 0; j < t2; j++)
{
if (m.find(s2[j]) == m.end() || m[s2[j]] <= 0)
return false;
m[s2[j]]--;
}


return true;
}




int main(){


    char s1[1000],s2[1000];
cin.getline(s1,1000);
cin.getline(s2,1000);
    cout<<is_include(s1,s2)<<endl;


return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值