题目描述:
在 Berland 流行着纸牌游戏 “Berlogging” ,这个游戏的赢家是根据以下规则确定的:在每一轮中,玩家获得或失去一定数量的分数,在游戏过程中,分数被记录在“名称和得分”行中,其中名字是玩家的名字,得分是在这一轮中获得的分数。得分是负值意味着玩家失去了相应的分数。如果在比赛结束时只有一名玩家分数最多,他就是获胜者。如果两名或两名以上的玩家在比赛结束时都有最大的分数 m,那么其中首先获得至少 m 分的玩家胜利。开始时,每个玩家都是0分。保证在比赛结束时至少有一个玩家的分数为正。
输入格式:
第一行包含整数n(1 <= n <= 1000),n 是游戏进行的的回合数。
第 2 ~ n+1 行,按照时间顺序输入“名称和得分”行的信息,其中名称是长度不大于 32 的小写字母组成的字符串,分数的绝对值不大于 1000。
输出格式:
输出获胜者的名称。
输入输出样例
输入 #1
3
mike 3
andrew 5
mike 2
输出 #1
andrew
题解:我们先定义string对应int的map映射。对每次输入进来的人名进行对应的分数操作。
但是,有可能会出现比赛结束后最大分相等的情况。所以我们就要结束之后再访问一遍,查找第一次大于等于最大分的情况。其他需要注意的地方这道题似乎就没有了。剩下的就是最基础的调用map。但是在最后最高分数不止一人的时候,找的获胜者是首先获得至少 m 分的玩家胜利,还要保证自己到最后的分数为最大者之一(自己第一次漏了这一点)!!!
AC代码:
#include<iostream>
#include<queue>
#include<map>
#include<cstdio>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
map<string,int>mp;
map<string,int>Q;
map<string,int>dp;
struct node{
string s;
int num;
}room[1005];
int main(){
int t;
string ss[1005];
scanf("%d",&t);
for(int i=1;i<=t;i++){
string str;
int k;
cin>>str>>k;
room[i].s=str;room[i].num=k;
mp[str]+=k;
Q[str]=i;
ss[i]=str;
}
int sum=0;
for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++){
if(it->second>=sum){
sum=it->second;
}
}
int flat=INF;
for(int i=1;i<=t;i++){
dp[room[i].s]+=room[i].num;
if(dp[room[i].s]>=sum&&mp[room[i].s]==sum){
flat=i;break;
}
}
cout<<ss[flat]<<endl;
}
题意描述:
当然,大家都熟悉井字棋游戏。 这些规则确实很简单。 两个玩家A、B轮流在3x3的方格的单元格中画符号(玩家A总是画“X”,玩家B总是画“0”)。 首先在水平、垂直或对角线上出现3个相同的符号的玩家获胜,比赛结束。 玩家A总是为先手。 如果3x3的方格被填满,但是在所有水平、垂直或对角线上均未出现3个相同的符号,宣布平局。
给你一个3*3的方格,每个单元格是“.”(空白),“X”或“0”。 你必须输出以下内容之一:
玩家A走棋(输出“first”)——如果出现给定的状态后,下一步为玩家A走棋。
玩家B走棋(输出“second”)——如果出现给定的状态后,下一步为玩家B走棋。
非法(输出“illegal”)——如果给定的状态无法在正常游戏过程中出现。
玩家A胜利(输出“the first player won”)——如果给定的状态中玩家A胜利。
玩家B胜利(输出“the second player won”)——如果给定的状态中玩家B胜利。
平局(输出“draw”)——如果给定的状态是平局。
输入输出样例
输入 #1
X0X
.0.
.X.
输出#1
second
输入 #2
XXX
0X0
X00
输出#2
the first player won
题解:
采用暴力枚举的方法,把每一种可能的情况都枚举一遍,时间复杂度O(1)。
注意illegalillegal的情况比较多,有以下几种:
(1)"0"的个数比"X"多。
(2)"X"的个数比"0"多两个及以上。
(3)先手获胜,但"0"的个数和"X"的个数一样。
(4)后手获胜,但"X"的个数比"0"的个数多1。
(5)先手和后手同时获胜。
如果棋盘是合法的,再判断谁输谁赢,或者是否是和棋。如果棋还没有下完,就判断该谁下了,如果"X"的个数和"0"的个数一样,就该先手走棋;如果"X"的个数比"0"多1,则该后手走棋。
AC代码:
#include<map>
#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<cmath>
#include<iomanip>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int main(){
string s[10];
for(int i=0;i<3;i++){
cin>>s[i];
}
int word=0;
int x=0,o=0;
for(int i=0;i<3;i++){
if(s[i].size()!=3){
word=1;break;
}
for(int j=0;j<3;j++){
if(s[i][j]!='.'&&s[i][j]!='X'&&s[i][j]!='0'){
word=1;break;
}
if(s[i][j]=='X') x++;
else if(s[i][j]=='0') o++;
}
}
//cout<<word<<endl;
if(word){cout<<"illegal"<<endl;return 0;}
int flat=0;
for(int i=0;i<3;i++){
if(s[i][0]=='X'&&s[i][1]=='X'&&s[i][2]=='X'){
flat++;
}
}
for(int i=0;i<3;i++){
if(s[0][i]=='X'&&s[1][i]=='X'&&s[2][i]=='X'){
flat++;
}
}
if(s[0][0]=='X'&&s[1][1]=='X'&&s[2][2]=='X') flat++;
if(s[0][2]=='X'&&s[1][1]=='X'&&s[2][0]=='X') flat++;
int ans=0;
for(int i=0;i<3;i++){
if(s[i][0]=='0'&&s[i][1]=='0'&&s[i][2]=='0'){
ans++;
}
}
for(int i=0;i<3;i++){
if(s[0][i]=='0'&&s[1][i]=='0'&&s[2][i]=='0'){
ans++;
}
}
if(s[0][0]=='0'&&s[1][1]=='0'&&s[2][2]=='0') ans++;
if(s[0][2]=='0'&&s[1][1]=='0'&&s[2][0]=='0') ans++;
//cout<<ans<<' '<<flat<<endl;
//if(ans>1||flat>1){cout<<"illegal"<<endl;return 0;}
if(ans!=0&&flat!=0) {cout<<"illegal"<<endl;return 0;}
int sum=x-o;
if(fabs(sum)==1||fabs(sum)==0){
if(x<o) {cout<<"illegal"<<endl;return 0;}
if(x>o){
if(x+o==9){
if(flat==0&&ans==0){cout<<"draw"<<endl;return 0;}
if(flat!=0&&ans==0){cout<<"the first player won"<<endl;return 0;}
if(flat==0&&ans!=0){cout<<"the second player won"<<endl;return 0;}
}
else{
if(flat!=0&&ans==0){cout<<"the first player won"<<endl;return 0;}
if(ans!=0) {cout<<"illegal"<<endl;return 0;}
cout<<"second"<<endl;return 0;
}
}
else if(x==o) {
if(flat!=0) {cout<<"illegal"<<endl;return 0;}
if(ans!=0) {cout<<"the second player won"<<endl;return 0;}
cout<<"first"<<endl;return 0;
}
}
else {cout<<"illegal"<<endl;return 0;}
}
题意翻译
题目描述
第一个国家级操作系统——BerlOS就要发布了。但是,它的一些功能还没有完善,比如内存管理系统。在开发者的计划里,第一版里的内存管理系统是简单并且是线性的。它将会支持以下操作:
alloc n —— 在内存中分配n字节的空间。此命令将返回已分配的内存块的编号x。
erase x —— 释放编号为x的内存块。
defragment —— 碎片整理,将所有内存块全部向内存的起点靠拢并且不改变它们的顺序。
整条内存一共有m个字节,每个字节依次编号为1,2,...,m。
操作 alloc 有一个参数n,表示需要分配n字节大小的内存块。在执行这个操作时,系统将把一块最靠近内存起点的,长度为n的连续空闲字节分配到一个内存块(这块内存块内的所有字节将被标记为“已使用”)。这个操作的返回值为这块内存块的编号。如果没有符合条件的内存块,返回 NULL 。
操作 erase 有一个参数x,表示需要释放的内存块的编号。它将释放这个内存块(这块内存块内的所有字节将被标记为“空闲”)。如果成功释放,不返回值;如果编号为x的内存块不存在,返回 ILLEGAL_ERASE_ARGUMENT 。
操作 deflagment 没有任何参数。它只是将所有内存块向前依次(编号小的地方)挪动直到它们紧挨在一起。(不改变它们的顺序)
你将用连续的正整数(1,2,...)作为每一个内存块的编号。比如,第i次分配的内存块编号为i。你的任务是依次输出所有 alloc 指令的返回值,以及所有执行失败的 erase 指令的返回值。 输入输出格式 输入格式
输入文件的第一行包括两个正整数 t 和 m 。 t 表示操作次数, m 表示内存大小(为m字节)。接下来的t行为每一次的命令。命令有以下三种:alloc 命令,后接一个整数 n ; erase 命令,后接一个整数 x ; defragment 命令。 输出格式
输出文件的每一行依次为每次执行的 alloc 函数的返回值或执行失败的 erase 函数返回的 ILLEGAL_ERASE_ARGUMENT 。
translated by 星烁晶熠辉
输入输出样例
输入 #1
6 10
alloc 5
alloc 3
erase 1
alloc 6
defragment
alloc 6
输出 #1
1
2
NULL
3
题解:简单模拟,坑点:没考虑x==0的情况,呜呜呜,坑死了一直在wrong第42个测试点!!!
if(k>=ans||k<=0){
cout<<"ILLEGAL_ERASE_ARGUMENT"<<endl;continue;
}
AC代码:
#include<iostream>
#include<string>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int a[1000],c[1000];
int main(){
int t,m;
scanf("%d%d",&t,&m);
int num=0;
int ans=1;
while(t--){
string str;int k;
cin>>str;
if(str=="alloc"){
cin>>k;
int num=0;
for(int i=1;i<=m;i++){
if(a[i]==0){
num++;
if(num==k){
for(int j=i;j>=i-k+1;j--){
a[j]=ans;
}
break;
}
}
else num=0;
}
if(num==k){
cout<<ans<<endl;ans++;
}
else cout<<"NULL"<<endl;
}
else if(str=="erase"){
cin>>k;
if(k>=ans||k<=0){
cout<<"ILLEGAL_ERASE_ARGUMENT"<<endl;continue;
}
int word=0;
for(int i=1;i<=m;i++){
if(a[i]==k){
a[i]=0;word=1;
}
}
if(word==0) cout<<"ILLEGAL_ERASE_ARGUMENT"<<endl;
}
else if(str=="defragment"){
int y=1;
memset(c,0,sizeof(c));
for(int i=1;i<=m;i++){
if(a[i]!=0){
c[y++]=a[i];
}
}
memset(a,0,sizeof(a));
for(int i=1;i<=m;i++){
if(c[i]!=0) a[i]=c[i];
}
}
}
}