简单模拟

这篇博客介绍了如何通过模拟来解决编程竞赛中的几个问题,包括家庭房产统计、日期问题和井字棋游戏。博主提供了题目的描述、输入输出格式以及样例,并给出了AC(Accepted)的解决方案,强调了在模拟过程中需要注意的细节和可能的陷阱。

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

D. Colored Boots

题意:

给定a串b串,里面有?,?可以变任何字母

求a串和b串字母个数相同的最多数目

解析:

直接模拟就可以了,先比a~z,在a~z和?匹配,如果?有多,?和?匹配

ac:

#include<bits/stdc++.h>
#define pb push_back
#define MAXN 500000
using namespace std;
 
char str[MAXN];
char ctr[MAXN];
queue<int> vca[100],vcb[100];
 
int aa[MAXN],bb[MAXN];
 
int main()
{
    int cnt=0;
    int n;
    scanf("%d",&n);
    scanf("%s",str+1);
    scanf("%s",ctr+1);
 
    for(int i=1;i<=n;i++)
    {
        if(str[i]=='?')
            vca[30].push(i);
        else  vca[str[i]-'a'+1].push(i);
        if(ctr[i]=='?')
            vcb[30].push(i);
        else  vcb[ctr[i]-'a'+1].push(i);
    }
 
    for(int i=1;i<=26;i++)
    {
        while(vca[i].size()>0&&vcb[i].size()>0)
        {
            aa[cnt]=vca[i].front();
            bb[cnt]=vcb[i].front();
            cnt++;
            vca[i].pop();
            vcb[i].pop();
        }
    }
 
    if(vca[30].size()>0)
    {
        for(int i=1;i<=26;i++)
        {
            while(vcb[i].size()>0&&vca[30].size()>0)
            {
                aa[cnt]=vca[30].front();
                bb[cnt]=vcb[i].front();
                cnt++;
                vcb[i].pop();
                vca[30].pop();
            }
        }
    }
 
    if(vcb[30].size()>0)
    {
        for(int i=1;i<=26;i++)
        {
            while(vca[i].size()>0&&vcb[30].size()>0)
            {
                aa[cnt]=vca[i].front();
                bb[cnt]=vcb[30].front();
                cnt++;
                vca[i].pop();
                vcb[30].pop();
            }
        }
    }
 
    while(vca[30].size()>0&&vcb[30].size()>0)
    {
        aa[cnt]=vca[30].front();
        bb[cnt]=vcb[30].front();
        cnt++;
        vca[30].pop();
        vcb[30].pop();
    }
 
    printf("%d\n",cnt);
    for(int i=0;i<cnt;i++)
        printf("%d %d\n",aa[i],bb[i]);
    return 0;
}

L2-007 家庭房产 (25 分)

给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。

输入格式:

输入第一行给出一个正整数N(≤1000),随后N行,每行按下列格式给出一个人的房产:

编号 父 母 k 孩子1 ... 孩子k 房产套数 总面积

其中编号是每个人独有的一个4位数的编号;分别是该编号对应的这个人的父母的编号(如果已经过世,则显示-1);k(0≤k≤5)是该人的子女的个数;孩子i是其子女的编号。

输出格式:

首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:

家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积

其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。

输入样例:

输入样例:

10
6666 5551 5552 1 7777 1 100
1234 5678 9012 1 0002 2 300
8888 -1 -1 0 1 1000
2468 0001 0004 1 2222 1 500
7777 6666 -1 0 2 300
3721 -1 -1 1 2333 2 150
9012 -1 -1 3 1236 1235 1234 1 100
1235 5678 9012 0 1 50
2222 1236 2468 2 6661 6662 1 300
2333 -1 3721 3 6661 6662 6663 1 100

输出样例:

3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000

解析:

用深搜求连通,也可以用并查集

ac:

#include<bits/stdc++.h>
#define pb push_back
#define MAXN 300005
using namespace std;
struct node
{
    int t;
    double val;
}ee[MAXN];//每个人的房子,价值
vector<int> ren[MAXN];//每个人的关系
int vis[MAXN];
set<int> st;
int cnt;

struct people
{
    int minp=9999999,num=0;
    double tao=0,mj=0,rj=0;
    bool friend operator <(people a,people b)
    {
        if(fabs(a.rj-b.rj)<0.000001)//要加fabs,否则段错误
            return a.minp<b.minp;
        else return a.rj>b.rj;
    }
}cc[MAXN];

void dfs(int x)
{
    cc[cnt].num++;
    cc[cnt].tao+=ee[x].t;
    cc[cnt].mj+=ee[x].val;
    if(x<cc[cnt].minp)
        cc[cnt].minp=x;
    int len=ren[x].size();
    for(int i=0;i<len;i++)
    {
        int v=ren[x][i];
        if(vis[v]==0)
        {
            vis[v]=1;
            dfs(v);
        }
    }
}

int main()
{
    int n,a,b,c,m,x,d;
    double e;
    cnt=0;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&a);
        scanf("%d%d",&b,&c);
        if(b!=-1)
        {
            ren[a].pb(b);
            ren[b].pb(a);
            st.insert(b);
        }
        if(c!=-1)
        {
            ren[a].pb(c);
            ren[c].pb(a);
            st.insert(c);
        }
        st.insert(a);
        scanf("%d",&m);
        while(m--)
            scanf("%d",&x);
        scanf("%d%lf",&d,&e);
        ee[a].t=d;
        ee[a].val=e;
    }
    set<int>::iterator it;
    for(it=st.begin();it!=st.end();it++)
    {
        int v=*it;
        if(vis[v]==0)
        {
            vis[v]=1;
            dfs(v);
            cc[cnt].rj=cc[cnt].mj*1.000000/cc[cnt].num;
            cnt++;
        }
    }
    sort(cc,cc+cnt);
    printf("%d\n",cnt);
    for(int i=0;i<cnt;i++)
        printf("%04d %d %.3f %.3f\n",cc[i].minp,cc[i].num,cc[i].tao*1.00000/cc[i].num,cc[i].rj);
    return 0;
}

[蓝桥杯][2017年第八届真题]日期问题

时间限制: 1Sec 内存限制: 128MB 提交: 268 解决: 35

题目描述

小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在1960年1月1日至2059年12月31日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

输入

一个日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)

输出

输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。多个日期按从早到晚排列。

样例输入

02/03/04

样例输出

2002-03-04
2004-02-03
2004-03-02

解析:

模拟就可以了,恶心人的题目

要注意很多细节,闰年,1960和2059,去重

ac:

#include<bits/stdc++.h>
using namespace std;
int cc[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};

int rn(int x)
{
    if((x%4==0&&x%100!=0)||(x%400==0))
        return 1;
    return 0;
}

int solve(int a,int b,int c)
{
    if(a>59)
        a=a+1900;
    else
        a=a+2000;
    if(b<1||b>12)
        return 0;
    if(c<1)
        return 0;
    if(rn(a)==1)
    {
        if(b==2)
        {
            if(c>29)
                return 0;
        }
        else if(c>cc[b])
            return 0;
    }
    else if(c>cc[b])
        return 0;
    return a*10000+b*100+c;
}

int aa[4]={0};

int main()
{
    int a,b,c;
    int x,y,z,cnt;
    cnt=0;
    scanf("%d/%d/%d",&a,&b,&c);
    x=solve(a,b,c);
    if(x!=0)
    {
        aa[cnt]=x;
        cnt++;
    }
    y=solve(c,a,b);
    if(y!=0)
    {
        aa[cnt]=y;
        cnt++;
    }
    z=solve(c,b,a);
    if(z!=0)
    {
        aa[cnt]=z;
        cnt++;
    }
    int cc=unique(aa,aa+cnt)-aa;
    sort(aa,aa+cc);
    for(int i=0;i<cc;i++)
    {
        printf("%02d-%02d-%02d\n",aa[i]/10000,(aa[i]%10000)/100,aa[i]%100);
    }
    return 0;
}

链接:https://ac.nowcoder.com/acm/contest/847/B
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

Alice和Bob正在下井字棋,顾名思义,在3*3棋盘上先完成三子连珠(横、竖,或者斜对角线)的玩家将获胜。

Alice执白子,Bob执黑子。

但是在下了几步后,Alice觉得这不好玩并失去了耐心,现在轮到他落子。他想知道他是否能在下一步立即获得游戏胜利。

本来这是个简单的判定,问题是Bob是很坏的,如果他发现Alice可以在下一步立即胜利,Bob会偷偷的偷走Alice一颗棋子而尽可能使得Alice不能立马赢得胜利。 给你当前的局况,你能帮助Alice弄清下一步能否获得胜利吗?

输入描述:

有多组测试样例。

第一行一个整数 T(T≤12000) T(T≤12000)--测试样例的个数。

接下来每三行表示一个样例,且每一行包含三个字符。
如果第 i i行第 j j个字符是'#'表示 (i,j) (i,j)这个位置是空的还没有被落子,如果是'W'则代表该位置有一个白子,'B'则代表该位置有一个黑子。
保证输入不存在已完成的三子连珠,不保证黑子和白子的数目相等,不保证有可以落子的点,如果没有点可以落子则默认Alice不能在下一步立即获得游戏胜利。
 

输出描述:

对每个样例输出一行。
如果Bob不偷走Alice的棋子Alice也不能在下一步立即获得游戏胜利,请输出"Bob"。
如果Bob需要偷走Alice的一颗棋子才能使Alice不能在下一步立即获得游戏胜利,请输出"Emmm"。
如果即使Bob偷走Alice的一颗棋子Alice也能在下一步立即获得游戏胜利,请输出"Alice"。

示例1

输入

1
W#W
BWB
#B#

输出

Alice

示例2

输入

1
W##
BBW
BWB

输出

Bob

示例3

输入

1
W#W
B#B
#B#

输出

Emmm

解析:

如果所以的成3方法中,(呢两个连在一起的棋子)都含有某个棋子,那么就Emmm,否则Alice

如果不能成3,Bob

ac:

#include<bits/stdc++.h>
using namespace std;
char mp[4][4]={0};
int xx[4][4]={0};
int vis[10]={0};
int ans=0;

void init()
{
    int vv=1;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            xx[i][j]=vv++;
}

void tt(int x,int y,int a,int b)
{
    int aa=xx[x][y];
    int bb=xx[a][b];
    vis[aa]++;
    vis[bb]++;
    ans++;
}

void solve()
{
    for(int i=1;i<=3;i++)
    {
        if(mp[i][1]=='W'&&mp[i][2]=='W'&&mp[i][3]=='#')
            tt(i,1,i,2);
        if(mp[i][1]=='W'&&mp[i][2]=='#'&&mp[i][3]=='W')
            tt(i,1,i,3);
        if(mp[i][1]=='#'&&mp[i][2]=='W'&&mp[i][3]=='W')
            tt(i,2,i,3);
    }

    for(int i=1;i<=3;i++)
    {
        if(mp[1][i]=='W'&&mp[2][i]=='W'&&mp[3][i]=='#')
            tt(1,i,2,i);
        if(mp[1][i]=='W'&&mp[2][i]=='#'&&mp[3][i]=='W')
            tt(1,i,3,i);
        if(mp[1][i]=='#'&&mp[2][i]=='W'&&mp[3][i]=='W')
            tt(2,i,3,i);
    }

    if(mp[1][1]=='W'&&mp[2][2]=='W'&&mp[3][3]=='#')
        tt(1,1,2,2);
    if(mp[1][1]=='W'&&mp[2][2]=='#'&&mp[3][3]=='W')
        tt(1,1,3,3);
    if(mp[1][1]=='#'&&mp[2][2]=='W'&&mp[3][3]=='W')
        tt(2,2,3,3);

    if(mp[1][3]=='W'&&mp[2][2]=='W'&&mp[3][1]=='#')
        tt(1,3,2,2);
    if(mp[1][3]=='W'&&mp[2][2]=='#'&&mp[3][1]=='W')
        tt(1,3,3,1);
    if(mp[1][3]=='#'&&mp[2][2]=='W'&&mp[3][1]=='W')
        tt(2,2,3,1);
}

int main()
{
    int t;
    init();
    while(scanf("%d",&t)!=EOF)
    {
        while(t--)
        {
            memset(mp,0,sizeof(mp));
            memset(vis,0,sizeof(vis));
            ans=0;
            int flag=0;
            for(int i=1;i<=3;i++)
                scanf("%s",mp[i]+1);
            solve();
            for(int i=1;i<=9;i++)
                if(vis[i]==ans)
                    flag=1;
            if(ans==0)
                printf("Bob\n");
            else if(flag==1)
                printf("Emmm\n");
            else if(flag==0)
                printf("Alice\n");
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值