NEUQ-acm第二期训练Week1——代码源div2

第二期训练题目来源:Daimayuan Online Judge, div2
link

101特殊的正方形

题目描述

输入n,输出n行n列的由+.组成的正方形,其中最外面一圈全是+,第二圈全是.,…,对于第i圈,如果i是奇数,那么全是+,否则全是.

输入格式

一行,一个整数n。

输出格式

n行,为满足题目要求的正方形。注意不要有行末空格。

样例输入

10

样例输出

++++++++++
+........+
+.++++++.+
+.+....+.+
+.+.++.+.+
+.+.++.+.+
+.+....+.+
+.++++++.+
+........+
++++++++++

数据范围

对于100%的数据,保证2≤n≤100。

思路

创建n×n的数组,一圈一圈赋值

代码

#include <bits/stdc++.h>
using namespace std;
int n;
char mapp[105][105];
int main(){
    cin >> n;
    for(int i = 1; i <= n/2+1; i++){
        if(i%2!=0){
            for(int j = i; j <= n-i+1; j++) mapp[i][j]='+';
            for(int j = i; j <= n-i+1; j++) mapp[j][n-i+1]='+';
            for(int j = i; j <= n-i+1; j++) mapp[n-i+1][j]='+';
            for(int j = i; j <= n-i+1; j++) mapp[j][i]='+';            
        }
        else{
            for(int j = i; j <= n-i+1; j++) mapp[i][j]='.';
            for(int j = i; j <= n-i+1; j++) mapp[j][n-i+1]='.';
            for(int j = i; j <= n-i+1; j++) mapp[n-i+1][j]='.';
            for(int j = i; j <= n-i+1; j++) mapp[j][i]='.';            
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cout << mapp[i][j];
        }
        cout << endl;
    }
}

102走楼梯2

题目描述

楼梯有 n 阶,上楼可以一步上一阶,也可以一步上二阶。
但你不能连续三步都走两阶,计算走到第n阶共有多少种不同的走法。

输入格式

一行,一个数字,表示n。

输出格式

输出走楼梯的方式总数。

样例输入

6

样例输出

12
数据规模

对于100%的数据,保证n≤50。

思路

状态转移:
(1)前5个:第i阶为第i-1阶与第i-2阶的和
(2)从第6阶开始:第i阶可以从第i-1阶迈一步;可以从第i-2阶迈两步上来,
但是第i-2阶只能从i-3阶迈一步上来或者从i-5阶迈到i-4阶(一步)再迈到i-2阶(两步)
也即写为方程:
//状态转移:dp[i]=dp[i-1]+dp[i-2]; 前五个
//dp[i]=dp[i-1]+dp[i-3]+dp[i-5]; 之后的

代码

//状态转移:dp[i]=dp[i-1]+dp[i-2];  前五个
//dp[i]=dp[i-1]+dp[i-3]+dp[i-5];   之后的
#include <bits/stdc++.h>
using namespace std;
int n;
long long dp[55];  //int超范围
int main(){
    cin >> n;
    dp[0]=1;
    dp[1]=1;
    for(int i = 2; i <= n; i++){
        if(i<6) 
            dp[i]=dp[i-1]+dp[i-2];
        else{
            dp[i]=dp[i-1]+dp[i-3]+dp[i-5];
        }
    }
    cout << dp[n];
}

注意,n=50时超出int范围,故用long long

103走路

题目描述

有一条很长的数轴,一开始你在0的位置。接下来你要走n步,第i步你可以往右走 a i a_i ai 或者 b i b_i bi

问n步之后,0到m的每个位置,能不能走到?

输入格式

第一行,两个整数n,m。

接下来n行,每行两个整数 a i , b i a_i,b_i ai,bi

输出格式

一行,一共m+1个数,每个数都是0或1表示能否走到,数字之间不用空格隔开。

输入样例

3 10
1 2
2 6
3 3

输出样例

00000011001
数据规模

对于所有数据,保证 1 ≤ n ≤ 100 , 1 ≤ m ≤ 105 , 1 ≤ a i , b i ≤ 1000 1≤n≤100,1≤m≤105,1≤a_i,b_i≤1000 1n100,1m105,1ai,bi1000

思路

简单来说就是看n步之后会落在哪里,可以dfs,但我怕超时,用了滚动数组
c[步数][位置]=1or0,主要看前一个减去本次需要走的步数时有没有走过

代码

#include <bits/stdc++.h>
using namespace std;
const int maxx = 1e5+5;
int n, m;
int a[maxx], b[maxx],c[105][maxx];
int main(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++)  cin >> a[i] >> b[i];
    memset(c,0,sizeof(c));
    c[0][0]=1;
    for(int i = 1; i <= n; i++){
        for(int j = a[i]; j <= m; j++){
           // cout << c[i-1][j-a[i]];
            if(c[i-1][j-a[i]]) c[i][j]=1;
        }
        for(int j = b[i]; j <= m; j++){
            if(c[i-1][j-b[i]]) c[i][j]=1;  
        }

    }
    for(int i = 0; i <= m; i++){
        cout << c[n][i];
    }
}

104简单分数统计

题目描述

N 个好朋友在codeforces上参加一场包含 M 个题目的比赛, 比赛期间codeforces网站一共有 k 次提交。

已知每个题目的分数,但是由于他们只能查到在比赛期间codeforces总共的提交记录(其他用户提交的其他题目记录也包含在内, 即存在不属于该场比赛的题目),

所以想请你编写一个程序算出他们每个人的分数。

输入格式

第一行三个整数 N, M, K 分别表示好朋友的个数, 题目的个数, 和提交的总次数(其中0<N,M,K<=200)。

接下来 N 行 第 i 行输入为第 i 个人的id,

接下来 M 行 第 j 行输入为第 j 个题目的名称和分数,

接下来 K 行 第 k 行输入为第 k 次提交的提交者id, 题目名称和结果(“WA” 或 “AC”, 如果"AC"代表通过这个题目, 提交者获得对应分数)。

注: 题目名称和id均为仅包含英文字母和数字的字符串, 题目分数为小于等于 1e6 的正整数. 每一行的多个输入之间用空格隔开。

所有输入的字符串长度 length 满足 0<length≤500。

所有用户id和题目名称不存在重名, 用户AC了某个题之后之后不会再重复提交该题, 好朋友们只会提交属于比赛的题目。

输出格式

输出 N 行, 第 i 行输出第 i 个人的名字和对应分数 (名字和分数用空格隔开)。

样例输入

2 2 4
GabrielPessoa
beza
metebronca 100
geometry 200
beza metebronca AC
ffern numbertheory AC
GabrielPessoa geometry WA
beza geometry AC

样例输出

GabrielPessoa 0
beza 300

样例解释

beza 过了 metebronca和geometry 拿到 300 分。
GabrielPessos 没有过题, 所以是 0 分。
还有一些其他选手提交的其他题目忽略不计。

思路

判断k个提交里的人名、题目名、是否ac

代码

#include <bits/stdc++.h>
using namespace std;
const int Max1 = 205;
const int Max2 = 1e6+5;
int n, m, k;
string id[Max1], name[Max1];
int score[Max1], manfen[Max1];
string a,b,c;
int main(){
    cin >> n >> m >> k;
    memset(score,0,sizeof(score));
    for(int i = 1; i <= n; i++) cin >> id[i];
    for(int i = 1; i <= m; i++) cin >> name[i] >> manfen[i];
    for(int i = 1; i <= k; i++){
        cin >> a >> b >> c;
        for(int j = 1; j <= n; j++){
            if(a==id[j]){
                if(c=="AC"){
                    for(int k = 1; k <= m; k++){
                        if(b==name[k]) score[j]+=manfen[k];
                    }
                }
            }
        }
    }
    
    for(int i = 1; i <= n; i++){
        cout << id[i] << " " << score[i] << endl;
    }
}

105Alice的德州扑克

题目描述

德州扑克是目前世界上最流行的扑克游戏,全世界有众多相关的比赛,例如是 WSOP,WPT,EPT等,也让这款游戏的玩法变得层出不穷,丰富多变。 不要被简单的游戏规则而误导,复杂多变的比赛状况,让这款游戏在高水平的竞技中会变得非常复杂,这也让人们为德州扑克给出了这样一句评价 ”用一刻就能学会,但要用一生才能掌握” 。

现在我们并不在乎游戏规则是什么,因为 Alice 是一个德州扑克高手,他对于德州扑克的规则烂熟于心,不过他每次都记不得牌型的大小关系,他知道你是一个编程高手,所以他想让你帮他写一个程序:输入五张牌的大小和花色,输出这五张牌能组成的最大牌型.你能帮帮他吗?

为了降低你的编程难度,我们规定:

1. 输入的牌都是来源于同一副扑克牌
2. 输入的牌的点数都是非递减的
3. 所有花色没有大小之分

下面给出各牌型,(从大到小)

  • 皇家同花顺(ROYAL FLUSH):五张顺连的牌(点数连续单调递增),且最大的一张牌是A(Ace),并且五张牌的花色相同

  • 同花顺(STRAIGHT FLUSH):五张顺连的牌(点数连续单调递增),不规定最大的一张牌是A(Ace),并且五张牌的花色相同

  • 四条(FOUR OF A KIND):至少四张牌的点数相同

  • 葫芦(FULL HOUSE):至少三张牌的点数相同,并且除此之外还有两张牌的点数相同

  • 同花(FLUSH):五张牌的花色都相同

  • 顺子(STRAIGHT):五张顺连的牌(点数连续单调递增),不要求五张牌的花色相同

特别注意:由于 Alice 是个谨慎的人,所以比 三条(THREE OF A KIND) (包括三条) 小的牌型 Alice 不在乎他们的大小关系,你只需要告诉 Alice 弃牌就行

输入格式

输入两行,每行五个数字,第一行的第 i 个字符表示第 i 张扑克的点数,

第二行的第 i 个数字表示第 i 张扑克花色。(保证输入的牌的点数是非递减的,且所有输入均合法)。

点数和对应输入的数字:

  • 2−10 对应 2 - 10
  • J(Jack) 对应 11
  • Q(Queen) 对应 12
  • K(King) 对应 13
  • A(Ace) 对应 14

花色和对应输入的数字:

  • 黑桃 (Spades) 对应 1
  • 方片 (Diamonds) 对应 2
  • 红桃 (Hearts) 对应 3
  • 梅花 (Clubs) 对应 4

输出格式

输出这五张牌能组成的最大牌型。

  • 如果最大是皇家同花顺输出 “ROYAL FLUSH”
  • 如果最大是同花顺输出 “STRAIGHT FLUSH”
  • 如果最大是四条输出"FOUR OF A KIND"
  • 如果最大是葫芦输出 “FULL HOUSE”
  • 如果最大是同花输出 “FLUSH”
  • 如果最大是顺子输出"STRAIGHT"
  • 如果最大的牌型小于等于三条输出"FOLD",劝 Alice 弃牌
  • 输出不包括引号

样例输入1

10 11 12 13 14
1 1 1 1 1

样例输出1

ROYAL FLUSH

样例输入2

10 11 12 13 14
1 2 1 3 4

样例输出2

STRAIGHT

样例输入3

6 6 6 7 7
1 2 3 1 3

样例输出3

FULL HOUSE

样例输入4

3 3 6 6 9
1 2 1 2 1

样例输出4

FOLD

在这里插入图片描述

思路

先判断是否成顺、成花,再加强条件,成条单独判断,其余的都是弃牌情况

代码

#include <bits/stdc++.h>
using namespace std;
struct p{
    int rand;
    int hua;
    bool operator<(p a){
        return rand <= a.rand;
    }
}pai[5];
string ans[7]={"ROYAL FLUSH", "STRAIGHT FLUSH", "FOUR OF A KIND", "FULL HOUSE",  "FLUSH", "STRAIGHT", "FOLD"};
int ind=7;
int t(p d[]){
    if(d[0].rand==d[1].rand && d[0].rand==d[2].rand && d[0].rand==d[3].rand && d[0].rand==d[4].rand) return 4;
    else if(d[0].rand==d[1].rand && d[0].rand==d[2].rand && d[0].rand==d[3].rand) return 4;
    else if(d[1].rand==d[2].rand && d[1].rand==d[3].rand && d[1].rand==d[4].rand) return 4;
    else if(d[0].rand==d[1].rand && d[0].rand==d[2].rand && d[3].rand==d[4].rand) return 3;
    else if(d[0].rand==d[1].rand && d[2].rand==d[3].rand && d[3].rand==d[4].rand) return 3;
    else  return 9;
}
int main(){
    for(int i = 0; i < 5; i++)  cin >> pai[i].rand;
    for(int i = 0; i < 5; i++)  cin >> pai[i].hua;
    int nowr=pai[0].rand, nowh=pai[0].hua;
    //成顺、成花
    int flag1=1, flag2=1, flag3=1;
    for(int i = 1; i < 5; i++){
        if(pai[i].rand==nowr+1) {flag1++;nowr=pai[i].rand;}
        if(pai[i].hua==nowh) {flag2++;}
    }
    if(flag1==5){
        if(flag2==5 && pai[4].rand==14) ind=1;
        else if(flag2==5)  ind = 2;
        else  ind = 6;
    }
    else if(flag2==5) ind = 5;
    else if(t(pai)==4) ind=3;
    else if(t(pai)==3) ind=4;
    else ind = 7;
    cout << ans[ind-1];
}

201任务分配

题目描述

你有n个任务,其中第i个任务,在 s i s_i si开始, e i e_i ei时刻结束,如果做这个任务,你能获得 w i w_i wi的收益。

但是你在一个时刻只能做一个任务,问选择哪些任务,能让你的收益尽量大。

注意:你在上一个任务结束后马上开始下一个任务是可以的。

输入格式

第一行一个整数n。

接下来n行,每行三个整数 s i , e i , w i s_i,e_i,w_i si,ei,wi

输出格式

一个数,表示答案。

样例输入

3
1 3 100
2 4 199
3 5 100

样例输出

200

思路

贪心,再时间t内选取价值最大的任务选择
在时间i内,如何选择以时间i结束的任务的方程dp[i]=max(dp[i],dp[ren[j].s]+ren[j].w)

代码

#include <bits/stdc++.h>
using namespace std;
const int Max = 1e3+5;
int n;
struct r{
    int s,e,w;
    bool operator <(r q){
        return e <= q.e || (e==q.e && s <= q.s); 
    }
}ren[Max];
int dp[Max];
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> ren[i].s >> ren[i].e >> ren[i].w;
    }
    sort(ren+1,ren+n+1);
    int maxe = ren[n].e;
    int now=0;
    dp[0]=0;
    for(int i = 1; i <= maxe; i++){
       dp[i]=dp[i-1];
       for(int j = 1; j <= n; j++){
        if(i==ren[j].e){
            dp[i]=max(dp[i],dp[ren[j].s]+ren[j].w);
        }
       }
    }
    cout << dp[maxe];
}

**注意:**要按结束时间的早晚排好序

202路径计数

题目描述

有一个n×n的网格,有些格子是可以通行的,有些格子是障碍。

一开始你在左上角的位置,你可以每一步往下或者往右走,问有多少种走到右下角的方案。

由于答案很大,输出对109+7取模的结果。

输入格式

第一行一个正整数n。

接下来n行,每行n个正整数,1表示可以通行,0表示不能通行。

输出格式

一个整数,表示答案。

样例输入

3
1 1 1
1 0 1
1 1 1

样例输出

2

思路

倒着想,到达(i, j)点的方法有哪些
(1)如果这个点上左都通,则dp[i][j]=(dp[i-1][j]+dp[i][j-1])
(2)如果只有一个通,则dp[i][j]=dp[i-1][j]或dp[i][j]=dp[i][j-1]
(3)如果都不通,则 dp[i][j]=0
所有点都遍历一边即可知道答案

代码

#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9+7;
int n;
int mapp[105][105];
long long dp[105][105];
long long ans;
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> mapp[i][j];
        }
    }
    dp[1][1]=1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(mapp[i-1][j]==1 && mapp[i][j-1])
                dp[i][j]=(dp[i-1][j]+dp[i][j-1])%mod;
            else if(mapp[i-1][j]==1)
                dp[i][j]=dp[i-1][j]%mod;
            else if(mapp[i][j-1]==1)
                dp[i][j]=dp[i][j-1]%mod;
            else
                dp[i][j]=0;
            dp[1][1]=1;
        }
    }
    cout << dp[n][n];
}

**注意:**dp[1][1]=1

203最大和上升子序列

题目描述

给定一个长度为 n 的数组 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an,问其中的和最大的上升子序列。也就是说,我们要找到数组 p 1 , p 2 , … , p m p_1,p_2,…,p_m p1,p2,,pm,满足 1 ≤ p 1 < p 2 < ⋯ < p m ≤ n 1≤p_1<p_2<⋯<p_m≤n 1p1<p2<<pmn 并且 a p 1 < a p 2 < ⋯ < a p m a_{p_1}<a_{p_2}<⋯<a_{p_m} ap1<ap2<<apm,使得 a p 1 + a p 2 + ⋯ + a p m a_{p_1}+a_{p_2}+⋯+a_{p_m} ap1+ap2++apm最大。

输入格式

第一行一个数字 n。

接下来一行 n 个整数 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an

输出格式

一个整数,表示答案。

样例输入

6
3 7 4 2 6 8

样例输出

21
数据规模

所有数据保证 1 ≤ n ≤ 1000 , 1 ≤ a i ≤ 1 0 5 1≤n≤1000,1≤a_i≤10^5 1n1000,1ai105

思路

遍历一遍,算出对于每个 a i a_i ai的最大上升序列和,对这n个和取最大即可

代码

#include <bits/stdc++.h>
using namespace std;
int n;
int a[1005];
long long dp[1005];
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }
    
    for(int i = 1; i <= n; i++){
        dp[i]=a[i];
        for(int j = i-1; j >= 0; j--){
            if(a[j]<a[i])
                dp[i]=max(dp[i],dp[j]+a[i]);
        }
    }
    long long x=0;
    for(int i= 1; i <= n; i++){
       // cout << dp[i] << " ";
        x = max(x,dp[i]);
    }
    cout << x ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

是夕颜呀

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值