程序设计与算法基础1-2

练习使用多case解题

Description
多CASE的问题在般有3种情形:(1)有一个数字开始表明CASE数目;(2)以特殊标志表示结束;(3)要求处理到最后一行。
现要求你在程序一次运行中,依次处理上述3种情况。

有三批测试数据,第1批测试数据,开头会以一个数字告之该批CASE数量,每一个CASE是两个正整数;
第1批测试数据结束后,紧接着是第2批数据,每一个CASE同样是两个正整数,第2批测试数据以两个0结束;
第2批测试数据结束后,紧接着是第3批数据,每一个CASE也是两个正整数,第3批测试数据一直到数据输入结束;

要求,每一个CASE,输出两数的最小公倍数
第1批测试数据处理完毕时,输出“group 1 done”
第2批测试数据处理完毕时,输出“group 2 done”
第3批测试数据处理完毕时,输出“group 3 done”

输入格式
有三批测试数据,第1批测试数据,开头会以一个数字告之该批CASE数量,每一个CASE是两个正整数(最大2的31次方);
第1批测试数据结束后,紧接着是第2批数据,每一个CASE同样是两个正整数,第2批测试数据以两个0结束;
第2批测试数据结束后,紧接着是第3批数据,每一个CASE也是两个正整数,第3批测试数据一直到数据输入结束;

输出格式
要求,每一个CASE,输出两数的最小公倍数
第1批测试数据处理完毕时,输出“group 1 done”
第2批测试数据处理完毕时,输出“group 2 done”
第3批测试数据处理完毕时,输出“group 3 done”

输入样例
2
6 10
5 12
8 16
12 18
8 4
0 0
4 5
4 6

输出样例
30
60
group 1 done
16
36
8
group 2 done
20
12
group 3 done

#include <iostream>
using namespace std;
typedef long long ll;
ll gcd(ll m,ll n)
{
    if(n==0) return m;
    else return gcd(n,m%n);

}
int main()
{
    ll t,m,n;
    cin>>t;
    while(t--)
    {
        cin>>m>>n;
        cout<<m*n/gcd(m,n)<<endl;
    }
    printf("group 1 done\n");

    while(scanf("%lld %lld",&m,&n)==2&&(m+n))
    {
         cout<<m*n/gcd(m,n)<<endl;
    }
    printf("group 2 done\n");

    while(~scanf("%lld %lld",&m,&n))
    {
        cout<<m*n/gcd(m,n)<<endl;
    }
    printf("group 3 done\n");
    return 0;
}

丑数

Description
“丑数”是指除了质因子2,3,5,不含其它质因子的正整数,例如由小到大前10个“丑数”为
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, …
现要求编写一个程序,输出指定第几位的“丑数”。
输入格式
第一行为正整数T(T<=10000), 表示case的数目。
此后T行,每行一个正整数 n (n <= 100000000).
输出格式
每一个n,输出第n个“丑数”
输入样例
3
1
2
9
输出样例
1
2
10

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
ll ugly[N];
ll n;
int main()
{
	ll t,n;
	ugly[1] = 1;
	ll a = 1, b = 1, c = 1;
	for (ll i = 2; i <= N; i++)
	{
		ugly[i] = min(ugly[a] * 2, min(ugly[b] * 3, ugly[c] * 5));
		if (ugly[i] == ugly[a] * 2)  a++;
		if (ugly[i] == ugly[b] * 3)  b++;
		if (ugly[i] == ugly[c] * 5)  c++;
	}
	cin >> t;
	while (t--)
	{
		cin >> n;
		cout << ugly[n] << endl;
	}
	return 0;
}

走迷宫

Description
有一个N*M(N,M<=10)的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,人在迷宫中可以尝试上下左右四个方向移动。
另外,在迷宫中如果从左边走出迷宫会回到迷宫最右边一格(只要该格不是墙),行不变,同样,从右边走出迷宫会
回到迷宫最左边一格,向上走出迷宫会回到迷宫最下边一格,向下走出迷宫会回到迷宫最上边一格。
现在给定一个迷宫,以及起点和终点,问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。
输入格式
该程序为多CASE,第1行为CASE的数量
每一个CASE,第1行为两个数N(行)和M(列)
然后N行每行M个数,之后是起点坐标和终点坐标sc(行) sr(列) ec(行) er(列)
输出格式
如题
输入样例
2
4 3
011
010
110
110
0 0 3 2
2 2
01
10
0 0 1 1
输出样例
4
die

#include <iostream>
#include <queue>
using namespace std;
typedef pair<int,int> P;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        char map1[105][105];
        int step[105][105];
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                cin>>map1[i][j];
                step[i][j]=-1;
            }
        }
        int sc,sr,ec,er;
        cin>>sc>>sr>>ec>>er;
        step[sc][sr] = 0;
        queue<P> q;
        q.push({sc,sr});
        while(!q.empty())
        {
            P t = q.front();
            q.pop();
            if(t.first==ec&&t.second==er)
                break;
            int dx[4] = {0,1,0,-1};
            int dy[4] = {1,0,-1,0};
            for(int i=0;i<4;i++)
            {
                int tx = t.first+dx[i];
                int ty = t.second+dy[i];
                if(tx<0) tx= n-1;
                if(tx==n) tx = 0;
                if(ty<0) ty = m-1;
                if(ty==m) ty=0;

                if(step[tx][ty]==-1&&map1[tx][ty]!='1')
                {
                    q.push({tx,ty});
                    step[tx][ty] = step[t.first][t.second]+1;
                }
            }

        }
        if(step[ec][er]==-1) cout<<"die"<<endl;
        else cout<<step[ec][er]<<endl;

    }

    return 0;
}

走迷宫2

Description
有一个N*M的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,另外,在迷宫中
有一些传送门,走到传送门的入口即会自动被传送到传送门的出口(一次传送算1步)。人在迷宫中可以尝试
上下左右四个方向移动。现在给定一个迷宫和所有传送门的出入口,以及起点和终点,
问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。
输入格式
该程序为多CASE,第1行为CASE的数量
每一个CASE,第1行为两个数N(行)和M(列)
然后N行每行M个数
之后是一个数W,为传送门的数量
之后每行一个传送门的入口坐标c1(行),r1(列)和出口坐标c2,r2
之后是起点坐标和终点坐标sc(行) sr(列) ec(行) er(列)
注:传送门出入口和起点坐标和终点坐标不会出现在墙的位置
所有数字不超过100
输出格式
如题
输入样例
2
4 3
011
011
110
110
1
1 0 2 2
0 0 3 2
2 2
01
10
0
0 0 1 1
输出样例
3
die

#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> P;
typedef struct Node
{
    int endx, endy;
}node;

node map2[105][105];
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n, m;
        char map[105][105];
        int step[105][105];
        cin >> n >> m;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                cin >> map[i][j];
                step[i][j] = -1;
            }
        }
        int w;
        cin >> w;
        while (w--)
        {
            int c1, r1, c2, r2;
            cin >> c1 >> r1 >> c2 >> r2;
            map2[c1][r1].endx = c2;
            map2[c1][r1].endy = r2;
            map[c1][r1] = '2';
        }
        int sc, sr, ec, er;
        cin >> sc >> sr >> ec >> er;
        step[sc][sr] = 0;
        queue<P> q;
        q.push({ sc,sr });
        while (!q.empty())
        {
            P t = q.front();
            q.pop();
            if (t.first == ec && t.second == er)
            {
                break;
            }
            if (map[t.first][t.second] == '2')
            {
                q.push({ map2[t.first][t.second].endx,map2[t.first][t.second].endy });
                step[map2[t.first][t.second].endx][map2[t.first][t.second].endy] = step[t.first][t.second] + 1;
            }
            else
            {
                int dx[4] = { 0,1,0,-1 };
                int dy[4] = { 1,0,-1,0 };
                for (int i = 0; i < 4; i++)
                {
                    int tx = t.first + dx[i];
                    int ty = t.second + dy[i];
                    if (tx>=0&&tx<n&&ty>=0&&ty<m&&step[tx][ty] == -1 && map[tx][ty] != '1')
                    {
                        q.push({ tx,ty });
                        step[tx][ty] = step[t.first][t.second] + 1;
                    }
                }
            }
        }
        if (step[ec][er] == -1)  cout << "die" << endl;
        else cout << step[ec][er] << endl;
    }
    return 0;
}

银行的叫号顺序

Description
银行的叫号过程是一个优先队列的典型应用,假设,银行有4类客户,分别用优先级1,2,3,4表示,级别越高
则更优先得到服务,例如,当前有三个人排队,两个1级客户,一个3级客户,则银行叫号时,3级客户将先得到服务
,即使另两个1级有客户比他先到。当多个同级的客户将获得服务时,由先到的客户先得到服务。
假设,银行只有一个服务窗口,一次只能服务一个客户,假设该窗口每5分钟服务一个客户,即叫号的时刻分别
为0分钟、5分钟、10分钟、…如果在叫号的时侯,没有客户,银行职员会去喝杯咖啡或上个洗手间,5分钟后
再继续叫号。
银行给出一系列客户到来的记录,每条记录包括“客户到来的时”,“客户等级”,“客户姓名”(由一个单词构成),请输
出银行服务的客户的顺序。
输入格式
第一数字是客户的数量n(n<=100000)
此后,每一行是一个客户来访信息,包括3个数字,到来的时刻(分钟整点,最大10的8次方)、等级、姓名(最多20个字母)
(已经按到来时刻排序)
输出格式
按服务的先后顺序输出客户的姓名
输入样例
4
0 1 John
3 1 Smith
3 1 Tom
4 2 Flod
输出样例
John
Flod
Smith
Tom

#include <iostream>
#include <queue>
using namespace std;

typedef pair<int, string> man;

priority_queue <man> q;

int main()
{
    int n;
    cin >> n;
    int t, lev, ret = 99999, realtime = 0;
    string name;
    while (n--)
    {
        cin >> t >> lev >> name;
        while (1)
        {
            if (t <= realtime)
            {
                q.push(make_pair(lev * 100000 + ret, name));
                ret -- ;
                break;
            }
            if (!q.empty())
            {
                cout << q.top().second << endl;
                q.pop();
            }
            realtime += 5;
        }
    }
    while (!q.empty())
    {
        cout << q.top().second << endl;
        q.pop();
    }
    return 0;
}

银行服务

Description
银行通过叫号来决定服务用户的顺序,假设,银行有4类客户,分别用优先级1,2,3,4表示,级别越高
则更优先得到服务,例如,当前有三个人排队,两个1级客户,一个3级客户,则银行叫号时,3级客户将先得到服务
,即使另两个1级的客户比他先到。当多个同级的客户将获得服务时,由先到的客户先得到服务。
假设,银行只有一个服务窗口,一次只能服务一个客户,假设该窗口每5分钟服务一个客户,即叫号的时刻分别
为0分钟、5分钟、10分钟、…如果在叫号的时侯,没有客户,银行职员会去喝杯咖啡或上个洗手间,5分钟后
再继续叫号。
有一种情况,银行工作到一定时间是要下班的,所以到一定时间,如果后面还有客户,将不再提供服务。
银行给出一系列客户到来的记录,每条记录包括“客户到来的时间”,“客户等级”,“客户姓名”(由一个单词构成),请输
出该银行这一轮服务的客户的顺序。
输入格式
第一行两个数字,第一数字是客户的数量n(n<=100000),第二个数字是银行关门的时间,到这个时间,即关门,该点及之后,
不再叫号,但之前已经叫号的客户会继续服务到完结。
此后,每一行是一个客户来访信息,包括3个数字,到来的时刻(分钟整点,最大10的8次方)、等级、姓名(最多20个字母)
(已经按到来时刻排序,注意:同一时刻可能会同时到来多个客户,这时若为同等级的,数据出现得早的稍早得到服务)
输出格式
按服务的先后顺序输出客户的姓名
输入样例
4 12
0 1 John
3 1 Smith
3 1 Tom
4 2 Flod
输出样例
John
Flod
Smith

#include <iostream>
#include <queue>
using namespace std;

typedef pair<int, string> man;

priority_queue <man> q;

int main()
{
    int n,ddl;
    cin >> n >> ddl ;
    int t, lev, ret = 99999, realtime = 0;
    string name;
    while (n--)
    {
        cin >> t >> lev >> name;
        while (1)
        {
            if (t <= realtime)
            {
                q.push(make_pair(lev * 100000 + ret, name));
                ret -- ;
                break;
            }
            if (realtime >= ddl) return 0;
            if (!q.empty())
            {
                cout << q.top().second << endl;
                q.pop();
            }
            realtime += 5;
        }
    }
    while (!q.empty()&&realtime<ddl)
    {
        cout << q.top().second << endl;
        q.pop();
        realtime += 5;
    }
    return 0;
}

勇者斗恶龙

Description
有n个头的恶龙,你希望雇一些骑士把它杀死(即砍掉所有头)。村里有m个骑士可以雇佣,一个能力值为x的骑士可以砍掉恶龙
一个直径不超过x的头,且需要支付x个金币。如何雇佣骑士才能砍掉恶龙的所有头,且需要支付的金币最少?注意,一个骑士只
能砍一个头(且不能被雇佣两次)
输入格式
多组数据,每组数据的第一行为正整数n和m(1<=n,m<=200000);以下n行每行为一个整数,即恶龙每个头的直径;以下m行每行为
一个整数,即每个骑士的能力。输入结束标志n=m=0;
输出格式
输出格式:每组数据,输出最少花费,无解输出"Loowater is doomed!"
输入样例
2 3
5
4
7
8
4
2 1
5
5
10
0 0
输出样例
11
Loowater is doomed!

#include <iostream>
#include <algorithm>
using namespace std;
int a[200005];
int b[200005];
int main()
{
    int n, m;
    while (scanf("%d%d", &n, &m) && n && m)
    {
        int i, k = 0, cnt= 0;
        for (i = 0; i < n; i++) scanf("%d", &a[i]);
        for (i = 0; i < m; i++) scanf("%d", &b[i]);
        sort(a, a + n);
        sort(b, b + m);
        for (i = 0; i < m; i++)
        {
            if (b[i] >= a[k])
            {
                cnt += b[i];
                k++;
                if (k == n) break;
            }
        }
        if (k < n) printf("Loowater is doomed!\n");
        else printf("%d\n", cnt);
    }
    return 0;
}

校赛排名

Description
校赛结束了,每一个参赛选手由3个数据项构成(通过题数,用时分钟数,姓名),排名按照通过题数排序
通过题数多的排前,同题数的,罚时少的排前。如果题数相同,罚时也相同,而按数据读取的先后排。
给你N个参赛选手的数据,按排序先后,输出姓名
输入格式
第一个数为N,(N<=500000)
此后,每行一个参赛选手的数据,通过题数,用时分钟数,姓名,前两者为整型数,姓名为字符串(不多于20个字符)
输出格式
姓名排名
输入样例
4
3 5 Jon
5 100 Smith
3 5 Tom
6 95 Hel
输出样例
Hel
Smith
Jon
Tom
提示
由于有500000个数据,输入和输出务必使用scanf和printf

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 500050;
typedef struct Stu
{
    int num;
    int time;
    char name[20];
    int order;
}stu;

bool cmp(stu a, stu b)
{
    if (a.num != b.num) return a.num > b.num;
    else if (a.num == b.num && a.time != b.time)  return a.time < b.time;
    else return a.order < b.order;
}

stu man[N];
int main()
{
    int n;
    scanf("%d", &n);

    for (int i = 0; i < n; i++)
    {
        scanf("%d %d %s", &man[i].num, &man[i].time, man[i].name);
        man[i].order = i;
    }
    sort(man, man + n,cmp);
    for (int i = 0; i < n; i++)
    {
        printf("%s\n", man[i].name);
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值