练习使用多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;
}