CSP3
A-瑞神的序列
1.题意:瑞神的数学一向是最好的,连强大的咕咕东都要拜倒在瑞神的数学水平之下,虽然咕咕东很苦 恼,但是咕咕东拿瑞神一点办法都没有。
  5.1期间大家都出去玩了,只有瑞神还在孜孜不倦的学习,瑞神想到了一个序列,这个序列长度为n,也就是一共有 个数,瑞神给自己出了一个问题:数列有几段?
  段的定义是连续的相同的最长整数序列
Input
输入第一行一个整数n,表示数的个数。
接下来一行n个空格隔开的整数,表示不同的数字

Output
输出一行,这个序列有多少段

Example
Input

12
2 3 3 6 6 6 1 1 4 5 1 4
1
2

Output
8

2.思路:该题较为简单,我们要做的操作就是判断前一个与后一个是否相同,如果不相同则最终结果ans加1.

3.代码:

#include <iostream>
using namespace std;int main()
{int* a=new int[1001];int num, ans, n;cin>>n;num=1001,ans=0;for(int i=0;i<n;i++){cin>>a[i];if(a[i]!=num){num=a[i];ans++;}}cout<<ans<<endl;return 0;
}

B-消消乐大师-Q老师
1.题意:Q老师是个很老实的老师,最近在积极准备考研。Q老师平时只喜欢用Linux系统,所以Q老师的电 脑上没什么娱乐的游戏,所以Q老师平时除了玩Linux上的赛车游戏SuperTuxKart之外,就是喜欢 消消乐了。
  游戏在一个包含有n 行m 列的棋盘上进行,棋盘的每个格子都有一种颜色的棋子。当一行或一列 上有连续三个或更多的相同颜色的棋子时,这些棋子都被消除。当有多处可以被消除时,这些地 方的棋子将同时被消除。
  一个棋子可能在某一行和某一列同时被消除。 由于这个游戏是闯关制,而且有时间限制,当Q老师打开下一关时,Q老师的好哥们叫Q老师去爬 泰山去了,Q老师不想输在这一关,所以它来求助你了!!
Input
输入第一行包含两个整数n,m,表示行数和列数
接下来n行m列,每行中数字用空格隔开,每个数字代表这个位置的棋子的颜色。数字都大于0.
Output
输出n行m列,每行中数字用空格隔开,输出消除之后的棋盘。(如果一个方格中的棋子被消除, 则对应的方格输出0,否则输出棋子的颜色编号。
Example
Input
4 5
2 2 3 1 2
3 1 1 1 1
2 3 2 1 3
2 2 3 3 3
Output
2 2 3 0 2
3 0 0 0 0
2 3 2 0 3
2 2 0 0 0

2.思路:我们可以将输入的矩阵存成两个,之后分别判断两个矩阵中行和列是否存在可消除的元素,若存在,则将对应位置置为零。输出时,只要两个矩阵中有一个对应位置为0,就输出0,即可得到正确答案。

3.代码:

#include<iostream>
#include<stdio.h>
using namespace std;int a[100][100], b[100][100];int main()
{int n, m, num, sum;cin>>n>>m;for(int i=0;i<n;i++)for(int j=0;j<m;j++){cin>>a[i][j];b[i][j] = a[i][j];}for(int i=0;i<n;i++)for(int j=0;j<m-1;j++){sum = 1;while(a[i][j]==a[i][j+1])sum++, j++; if(sum>=3){for(int temp = j;temp>j-sum;temp--)a[i][temp] = 0;}}for(int j=0;j<m;j++)for(int i=0;i<n-1;i++){sum = 1;while(b[i][j]==b[i+1][j])sum++, i++; if(sum>=3){for(int temp = i;temp>i-sum;temp--)b[temp][j] = 0;}}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(a[i][j]!=0&&b[i][j]!=0)cout<<a[i][j];elsecout<<0;if(j!=m-1)cout<<" ";}if(i!=n-1)cout<<endl;}return 0;
}

C-咕咕东学英语
1.题意:咕咕东很聪明,但他最近不幸被来自宇宙的宇宙射线击中,遭到了降智打击,他的英语水平被归零了!这一切的始作俑者宇宙狗却毫不知情!
  此时咕咕东碰到了一个好心人——TT,TT在吸猫之余教咕咕东学英语。今天TT打算教咕咕东字母A 和字母B,TT给了咕咕东一个只有大写A、B组成的序列,让咕咕东分辨这些字母。
  但是咕咕东的其他学科水平都还在,敏锐的咕咕东想出一个问题考考TT:咕咕东问TT这个字符串 有多少个子串是Delicious的。
  TT虽然会做这个问题,但是他吸完猫发现辉夜大小姐更新了,不想回答这个问题,并抛给了你, 你能帮他解决这个问题吗?
  Delicious定义:对于一个字符串,我们认为它是Delicious的当且仅当它的每一个字符都属于一个 大于1的回文子串中。
Input
输入第一行一个正整数n,表示字符串长度。
接下来一行,一个长度为n只由大写字母A、B构成的字符串。
Output
输出仅一行,表示符合题目要求的子串的个数
Example
Input
5
A A B B B
1
2
Output
6

2.思路:这题主要考察思维能力,正难则反。
根据题意,可以发现不合法的串只有以下4种情况
ABB…B B
BAA…AA
AA…AAB
BB…BBA
因此分类枚举所有不合法情况,然后减去不合法的就行了。
我们可以发现当序列是AB或BA开头时,那么满足条件的子串个数就是对应序列长度减去2;而当序列是AA或BB开头时,当AA…AB或BB…A的情况时,需要额外减去1.
找到第i个元素后第一个A 和第一个B,然后分情况谈论即可(以A开头为例,B同理),如果B的位置在A之后,那就需要额外减1;如果B的位置在A之前,那就不需要额外减1;
综上所述,我们只要遍历一遍整个序列就可完成统计。

3.代码:

#include <iostream>
#include <algorithm>
#define MAX 1000000
using namespace std;int n;
int a[MAX], b[MAX], b1[MAX];int main()
{char c;cin>>n;int cnt1, cnt2, temp1, temp2;long long int ans;cnt1 = 0, cnt2 = 0, ans = 0;for(int i=1;i<=n;i++){cin>>c;a[i] = c - 'A';if(a[i]==0)b[cnt1++] = i;elseb1[cnt2++] = i;}for(int i=1;i<=n-1;i++){temp1 = lower_bound(b, b + cnt1, i + 1) - b;//找到第i个元素后第一个A temp2 = lower_bound(b1, b1 + cnt2, i + 1) - b1;//找到第i个元素后第一个B temp1 = b[temp1], temp2 = b1[temp2];if(a[i]==1)swap(temp1, temp2);if(temp1!=0){if(temp2<temp1)ans = ans + n - temp1 + 1;elseans = ans + n - temp1;}}cout<<ans<<endl;
}

CSP4
A-TT数鸭子
1.题意:TT来到一个小湖边,看到了许多在湖边嬉戏的鸭子,TT顿生羡慕。此时他发现每一只鸭子都不一样,或羽毛不同,或性格不同。TT在脑子里开了一个map<鸭子,整数> tong,把鸭子变成了一些数字。现在他好奇,有多少只鸭子映射成的数的数位中不同的数字个数小于k。

Input
输入第一行包含两个数n,k,表示鸭子的个数和题目要求的k。
接下来一行有n个数,aiai a_iai​,每个数表示鸭子被TT映射之后的值。

Output
输出一行,一个数,表示满足题目描述的鸭子的个数。
注意无行末空格

2.思路:这道题的重点是求一个数中不相同的数字个数。因此可以将这个数看成字符串,里面的每一个数字就是一个字符,设立一个大小为10的int数组.当某个数字出现的时候,这个数组的对应位置 str[ i ] - '0’处的值就为1,最后看有几个位置是1就可以得出有几个不同的数字.

3.代码:

#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
using namespace std;char s[10];
int a[10];int main()
{int n, k, count, sum;cin>>n>>k;count = 0;char c;for(int i=0;i<n;i++){scanf("%s", s);sum = 0;for(int i=0;i<10;i++) a[i]=0;for(int i=0;i<strlen(s);i++)if(!a[s[i]-'0'])a[s[i]-'0']++, sum++;if(sum<k)count++;    }cout<<count<<endl;return 0;
}

B-ZJM要抵御宇宙射线
1.题意:据传,2020年是宇宙射线集中爆发的一年,这和神秘的宇宙狗脱不了干系!但是瑞神和东东忙 于正面对决宇宙狗,宇宙射线的抵御工作就落到了ZJM的身上。假设宇宙射线的发射点位于一个 平面,ZJM已经通过特殊手段获取了所有宇宙射线的发射点,他们的坐标都是整数。而ZJM要构 造一个保护罩,这个保护罩是一个圆形,中心位于一个宇宙射线的发射点上。同时,因为大部分 经费都拨给了瑞神,所以ZJM要节省经费,做一个最小面积的保护罩。当ZJM决定好之后,东东 来找ZJM一起对抗宇宙狗去了,所以ZJM把问题扔给了你~

Input
输入 第一行一个正整数N,表示宇宙射线发射点的个数
接下来N行,每行两个整数X,Y,表示宇宙射线发射点的位置

Output
输出包括两行
第一行输出保护罩的中心坐标x,y 用空格隔开
第二行输出保护罩半径的平方
(所有输出保留两位小数,如有多解,输出x较小的点,如扔有多解,输入y较小的点)
无行末空格

2.思路:由于本题数据量较小(<=1000),因此可以直接暴力求解.
对于每一个点,求出距它最远的那个点的距离,然后找出其中最小的输出即可。
题目中要求如有多解,输出x较小的点,如仍有多解,输入y较小的点。因此只要将各点排序一下即可。
注意:最后输出的是半径的平方,不能开方。

3.代码:

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<algorithm>
using namespace std;struct node
{long long int x, y;bool operator <(const node& m){return x==m.x ? y<m.y : x<m.x;}
};vector<node> vec;int main()
{int n, x, y;cin>>n;for(int i=0;i<n;i++){cin>>x>>y;vec.push_back({x, y});}sort(vec.begin(), vec.end());long long int temp = 0, r = 0, x2 = 0, y2 = 0, r1 = 1e15;int index = 0;for(int i=0;i<n;i++){r = 0;for(int j=0;j<n;j++){x2 = vec[i].x - vec[j].x, y2 = vec[i].y - vec[j].y;x2 *=x2, y2 *=y2;temp = x2+y2;r = max(temp, r);}if(r<r1)r1=r, index = i;        }printf("%lld.00 %lld.00\n", vec[index].x, vec[index].y);printf("%lld.00\n", r1);return 0;
}

C-宇宙狗的危机
1.题意:在瑞神大战宇宙射线中我们了解到了宇宙狗的厉害之处,虽然宇宙狗凶神恶煞,但是宇宙狗有一个很可爱的女朋友。
最近,他的女朋友得到了一些数,同时,她还很喜欢树,所以她打算把得到的数拼成一颗树。
这一天,她快拼完了,同时她和好友相约假期出去玩。贪吃的宇宙狗不小心把树的树枝都吃掉了。所以恐惧包围了宇宙狗,他现在要恢复整棵树,但是它只知道这棵树是一颗二叉搜索树,同时任意树边相连的两个节点的gcd(greatest common divisor)都超过1。
但是宇宙狗只会发射宇宙射线,他来请求你的帮助,问你能否帮他解决这个问题

Input
输入第一行一个t,表示数据组数。
对于每组数据,第一行输入一个n,表示数的个数
接下来一行有n个数
a
i
ai a_i
a
i,输入保证是升序的。

Output
每组数据输出一行,如果能够造出来满足题目描述的树,输出Yes,否则输出No。
无行末空格。

2.思路:本题准备全遍历一下。在构造左孩子节点和右孩子节点时,都遍历各个可能的情况,但是如果每一次都这样查找的话无疑会爆掉。因此一定要合理剪枝,为此开辟了四个bool数组l1、r1和can_l、can_r。l1和r1记录对应的区间是否被遍历过,如果被遍历过那么就直接查看对应的can_l或can_r。如果没有被遍历过,那么就先遍历一下。查看其能否构造成符合标准的左子树或右子树。为了避免多余的遍历,当我们证明一个可行的建树策略后就直接结束遍历。
最后还开辟了一个二维数组result用于记录各个数据之间的公约数,避免重复的计算。

3.代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;int gcd(int a,int b)
{return b == 0 ? a : gcd(b,a%b);
}int a[1000];
int n, judge;
int result[1000][1000];//记录最大公约数
bool l1[1000][1000]; //统计左区间是否遍历过
bool r1[1000][1000]; //统计右区间是否遍历过
bool can_l[1000][1000]; //记录左子树是否构建成功
bool can_r[1000][1000]; //记录右子树是否构建成功 bool gettree(int l, int r, int x)
{bool m = false;if(l>r)return true;for(int i=l;i<=r&&!m;i++){if(result[x][i]>1){if(!l1[l][i-1]){can_l[l][i-1] = gettree(l, i-1, i);l1[l][i-1] = true;} if(!r1[i+1][r]){can_r[i+1][r] = gettree(i+1, r, i);r1[i+1][r] = true;} if(can_l[l][i-1]&&can_r[i+1][r])m=true;}          }return m;
}int main()
{int t;cin>>t;while(t!=0){judge = false;memset(l1, false, sizeof(l1));memset(r1, false, sizeof(r1));memset(can_l, false, sizeof(can_l));memset(can_r, false, sizeof(can_r));cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){result[i][j] = gcd(a[i], a[j]);result[j][i] = result[i][j];}for(int i=1;i<=n&&!judge;i++){if(gettree(1, i-1, i)&&gettree(i+1, n, i))judge = true;  }if(!judge)cout<<"No"<<endl;elsecout<<"Yes"<<endl;t--;}
}

Week9作业
A-咕咕东的目录管理器
1.题意:建造一个目录管理器,初始时硬盘是空的,命令行的当前目录为根目录 root。目录管理器可以理解为要维护一棵有根树结构,同时每个目录的儿子必须保持字典序。并依次实现下列操作:

输出格式为:

Input
输入文件包含多组测试数据,第一行输入一个整数表示测试数据的组数 T (T <= 20);
每组测试数据的第一行输入一个整数表示该组测试数据的命令总数 Q (Q <= 1e5);
每组测试数据的 2 ~ Q+1 行为具体的操作 (MKDIR、RM 操作总数不超过 5000);
面对数据范围你要思考的是他们代表的 “命令” 执行的最大可接受复杂度,只有这样你才能知道你需要设计的是怎样复杂度的系统。

Output
每组测试数据的输出结果间需要输出一行空行。注意大小写敏感。

2.思路:题目要求一个目录能够根据子目录的名字取到它的子目录
故要用 map<string, 目录>,它可以根据 key 也就是 string 在内部进行排序。这样每次可以 log 级别复杂度取到子目录。
MKDIR s, 创建子目录操作:因为map可以按照key也就是string就行排序,那么直接向children数组中插入名字为s的目录即可,如果已存在同名子目录返回空指针。且为了后续的撤销操作,需要将插入的子目录存储到对应的cmlist数组中,撤销时调用RM操作即可。
RM s, 删除子目录操作:与插入操作基本一致,就是改为如果不存在目录名为s的子目录返回空指针,撤销时调用addchild函数即可,addchild函数具体实现与MKDIR基本一致。
CD s, 进入子目录操作:具体操作较为简单,就是要为撤销做准备,如果执行成功就将当前的目录存储到对应的cmlist数组中,然后再更新当前目录。撤销时直接从cmlist数组取出对应的目录,然后更新now即可。
SZ和LS都较为简单,就是TREE操作需要引入一个懒更新,避免重复遍历(否则会超时),为此需要引入一个bool类型的updated来记录当前的目录是否已经遍历过以及一个vector< string>* tenDescendants来保存当前目录的十个后代;
更新可以直接通过前序遍历直接更新十个后代;也可以先更新前五个,再更新后五个以避免多余的遍历。

3.代码:

#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
#include <string>
#include <string.h>
using namespace std;bool status = false;struct Command
{const string CMDNAMES[7]={"MKDIR","RM","CD","SZ","LS","TREE","UNDO"};int type;Command(string s){for(int i=0;i<7;i++){if(CMDNAMES[i] == s){type=i;return;}}}
};struct ContentNode
{string element;int size; ContentNode **child;ContentNode *father;ContentNode(string thePair):element(thePair){size = 0;child = NULL;}ContentNode(string thePair, int dsize):element(thePair){size = dsize;if(dsize!=0)child = new ContentNode* [dsize];}bool operator <(const ContentNode&t){return element<t.element;}
};vector<string> now;//记录当前目录
vector<int> act;//记录进行的操作,MKDIR或RM或CD
vector<string> s;//记录操作的目录
vector<ContentNode*> cmd;//用于记录被删除的结点 class Content
{public:Content(){string m = "root";root = new ContentNode(m);}~Content(){};void undo();void sz();void ls();void tree();void insert(string e);void insert(ContentNode* t1);void delete1(string e);void cd(string e);int getsize(ContentNode* t1);private:ContentNode *root;bool exist(ContentNode* t1, string e);void tree(ContentNode* t1, int &num, int &size1);ContentNode* preOrderfind(ContentNode *t,string e);ContentNode* prepare(ContentNode* t1, ContentNode* t2);
};
ContentNode* Content::preOrderfind(ContentNode *t,string e)//使用递归查找元素weie的节点
{ContentNode *p= NULL;int m = t->size, i = 0;if (t != NULL){if(t->element==e){p=t;return p;}while(i<m){p = preOrderfind(t->child[i], e);if(p!=NULL)return p;i++;}}return NULL;
}
bool Content::exist(ContentNode* t1, string e)
{int dsize = t1->size;for(int i=0;i<dsize;i++){ContentNode* node2 = t1->child[i];if(node2->element == e)return true;}return false;
}
ContentNode* Content::prepare(ContentNode* t1, ContentNode* t2)
{string element = t1->element;int dsize = t1->size+1;ContentNode* node = new ContentNode(element,dsize);if(dsize == 1){node->child[0]=t2;t2->father = node;return node;}int num = 0;string e = t2->element;for(int i=0;i<dsize-1;i++){if(e > t1->child[i]->element)num++;}for(int i=0;i<dsize;i++){if(i>=num&&i!=0){node->child[i] = t1->child[i-1];t1->child[i-1]->father = node;}  else{node->child[i] = t1->child[i];t1->child[i]->father = node;}  }node->child[num] = t2;t2->father = node;return node;
}
void Content::insert(string e)
{ContentNode* node = new ContentNode(e);this->insert(node);
}
void Content::insert(ContentNode* node2)
{string m = now[now.size() - 1];ContentNode* node1 = this->preOrderfind(root, m);string e = node2->element; if(exist(node1, e)){printf("ERR\n");return;}ContentNode* node3 = node1 -> father;ContentNode* dnode = prepare(node1, node2);if(!status)s.push_back(e);if(node1->element == "root")root = dnode; else{for(int i=0;i<node3->size;i++){node2 = node3->child[i];if(node1->element == node2->element){if(node3->element == "root"){root->child[i] = dnode;dnode->father = root;} else{node3->child[i] = dnode;dnode->father = node3;}        }   }}if(!status)act.push_back(0);printf("OK\n");
}
void Content::delete1(string e)
{string m = now[now.size()-1];ContentNode* node1 = this->preOrderfind(root, m);if(!exist(node1, e)){printf("ERR\n");return;}ContentNode* node2 = new ContentNode(node1->element);ContentNode* node3 = node1->father;for(int i=0;i<node1->size;i++){if(node1->child[i]->element != e)node2 = prepare(node2, node1->child[i]);else if(!status)cmd.push_back(node1->child[i]);}  if(node1->element =="root")root = node2;else if(node3->element =="root"){for(int i=0;i<root->size;i++){ContentNode* dnode = root->child[i];if(dnode->element==node1->element){root->child[i] = node2;node2->father = root;}     }}else{for(int i=0;i<node3->size;i++){ContentNode* dnode = node3->child[i];if(dnode->element==node1->element){node3->child[i] = node2;node2->father = node3;}      }}if(!status)act.push_back(1);printf("OK\n");
}
void Content::cd(string e)
{string m = now[now.size()-1];ContentNode* node1 = this->preOrderfind(root, m);if(!exist(node1, e)&&e!=".."){printf("ERR\n");return;}if(e!=".."){now.push_back(e);for(int i=0;i<node1->size;i++)ContentNode* node2 = node1->child[i];printf("OK\n");}else{string t = "..";now.pop_back();s.push_back(m);s.push_back(t);if(!now.empty())printf("OK\n");else{now.push_back(m);printf("ERR\n");}        }act.push_back(2);
}
void Content::sz()
{string m = now[now.size()-1];ContentNode* node1 = this->preOrderfind(root, m);printf("%d\n", getsize(node1) + 1);
}
void Content::ls()
{string m = now[now.size()-1];ContentNode* node1 = this->preOrderfind(root, m);if(node1->size>=1&&node1->size<=10){for(int i=0;i<node1->size;i++){ContentNode* node2 = node1->child[i];cout<<node2->element<<endl;}}else if(node1->size==0)printf("EMPTY\n");else {for(int i=0;i<5;i++){ContentNode* node2 = node1->child[i];cout<<node2->element<<endl;}printf("...\n");for(int i=node1->size-1;i>node1->size-5;i--){ContentNode* node2 = node1->child[i];cout<<node2->element<<endl;}}
}
void Content::tree(ContentNode *t, int &num, int &size1)//前序遍历
{num++;if(num<=5||num>size1-4)cout<<t->element<<endl;if(num==5&&size1>10)printf("...\n");for(int i=0;i<t->size;i++){ContentNode* node1 = t->child[i];tree(node1, num, size1);}
}
void Content::tree()
{string m = now[now.size()-1];ContentNode* node1 = this->preOrderfind(root, m);int size1 = getsize(node1), num = 0;this->tree(node1, num, size1);
}
int Content::getsize(ContentNode *t)
{int size1 = 0;size1 = size1+t->size;for(int i=0;i<t->size;i++){ContentNode* node1 = t->child[i];size1 = size1 + getsize(node1);} return size1;
}
void Content::undo()
{if(act.empty()){printf("ERR\n");return;}int m = act[act.size()-1];string e = s[s.size()-1];act.pop_back();status = true;switch(m){case 0:{this->delete1(e);s.pop_back();break;}case 1:{ContentNode* node = cmd[cmd.size()-1];this->insert(node);cmd.pop_back();break;}case 2:{if(e==".."){s.pop_back();e = s[s.size()-1];now.push_back(e);s.pop_back();}elsenow.pop_back();printf("OK\n");break;}}status = false;
}
int main()
{int t, q;string s1, e;scanf("%d", &t);for(int i=0;i<t;i++) {scanf("%d", &q);Content c1;s.clear(), act.clear(), now.clear();string e1 = "root";now.push_back(e1);for(int j=0;j<q;j++){cin>>s1;Command *cmd=new Command(s1);switch(cmd->type){case 0:{cin>>e;c1.insert(e);break;}case 1:{cin>>e;c1.delete1(e);break;}case 2:{cin>>e;c1.cd(e);break;}case 3:{c1.sz();break;}case 4:{c1.ls();break;}case 5:{c1.tree();break;}case 6:{c1.undo();break;}}}c1.~Content(); cout<<endl;}return 0;
}

B-东东学打牌
1.题意:
最近,东东沉迷于打牌。所以他找到 HRZ、ZJM 等人和他一起打牌。由于人数众多,东东稍微修改了亿下游戏规则:
所有扑克牌只按数字来算大小,忽略花色。
每张扑克牌的大小由一个值表示。A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K 分别指代 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13。
每个玩家抽得 5 张扑克牌,组成一手牌!(每种扑克牌的张数是无限的,你不用担心,东东家里有无数副扑克牌)
理所当然地,一手牌是有不同类型,并且有大小之分的。
举个栗子,现在东东的 “一手牌”(记为 α),瑞神的 “一手牌”(记为 β),要么 α > β,要么 α < β,要么 α = β。
那么这两个 “一手牌”,如何进行比较大小呢?首先对于不同类型的一手牌,其值的大小即下面的标号;对于同类型的一手牌,根据组成这手牌的 5 张牌不同,其值不同。下面依次列举了这手牌的形成规则:
(1)大牌:这手牌不符合下面任一个形成规则。如果 α 和 β 都是大牌,那么定义它们的大小为组成这手牌的 5 张牌的大小总和。
(2)对子:5 张牌中有 2 张牌的值相等。如果 α 和 β 都是对子,比较这个 “对子” 的大小,如果 α 和 β 的 “对子” 大小相等,那么比较剩下 3 张牌的总和。
(3)两对:5 张牌中有两个不同的对子。如果 α 和 β 都是两对,先比较双方较大的那个对子,如果相等,再比较双方较小的那个对子,如果还相等,只能比较 5 张牌中的最后那张牌组不成对子的牌。
(4)三个:5 张牌中有 3 张牌的值相等。如果 α 和 β 都是 “三个”,比较这个 “三个” 的大小,如果 α 和 β 的 “三个” 大小相等,那么比较剩下 2 张牌的总和。
(5)三带二:5 张牌中有 3 张牌的值相等,另外 2 张牌值也相等。如果 α 和 β 都是 “三带二”,先比较它们的 “三个” 的大小,如果相等,再比较 “对子” 的大小。
(6)炸弹:5 张牌中有 4 张牌的值相等。如果 α 和 β 都是 “炸弹”,比较 “炸弹” 的大小,如果相等,比较剩下那张牌的大小。
(7)顺子:5 张牌中形成 x, x+1, x+2, x+3, x+4。如果 α 和 β 都是 “顺子”,直接比较两个顺子的最大值。
(8)龙顺:5 张牌分别为 10、J、Q、K、A。
作为一个称职的魔法师,东东得知了全场人手里 5 张牌的情况。他现在要输出一个排行榜。排行榜按照选手们的 “一手牌” 大小进行排序,如果两个选手的牌相等,那么人名字典序小的排在前面。
不料,此时一束宇宙射线扫过,为了躲避宇宙射线,东东慌乱中清空了他脑中的 Cache。请你告诉东东,全场人的排名

Input
输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况。

Output
对于每组测试数据,输出 n 行,即这次全场人的排名。

2.思路:通过分析8种牌型,我们可以知道为了比较各种牌,我们除了要知道这五张牌的牌型外,还要知道sum, p1, p2三个排序关键字,其中sum是5张牌种个数为1的牌的数值和;当牌型为两对时,p1记录的是两对种较大的那一对的数值,p2记录的是两对中较小的那一对的数值;当牌型为三带二时,p1记录的是三条的数值,p2记录的是一对的数值;依次类推,p1记录的始终是比较优先级更高的数值。然后重载<,依次按照牌型,p1,p2,sum降序排列,如果前四者都相同,则按照名字的字典序升序排列。

3.代码:

#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;struct card
{string s;int type, sum, p1, p2;bool operator < (const card &c) const{if(type != c.type)return type>c.type;else if(p1 != c.p1)return p1>c.p1;else if(p2 != c.p2)return p2>c.p2;else if(sum != c.sum)return sum > c.sum;elsereturn s < c.s;        }
};void solve(string s, card &num)
{int j=0, a[14] = {0}, b[5] = {0};int sum = 0, c0 =0, c1 = 0, c2 = 0;for(int i=0;i<s.size();i++){if(s[i+1] =='0'){b[j] = 10;i++;}else if(s[i]=='A')b[j] = 1;else if(s[i]=='J')b[j] = 11;else if(s[i]=='Q')b[j] = 12;else if(s[i]=='K')b[j] = 13;else b[j] = s[i] - '0';j++;   }sort(b, b+5);int p1 = 0, p2 = 0;for(int i=0;i<5;i++)a[b[i]]++;for(int i=1;i<14;i++){if(a[i]==2){c0++;if(!p2)p2 = i;elsep1 = i;} else if(a[i]==3){c1++;p1 = i;}     else if(a[i]==4){c2++;p1 = i;} else if(a[i]==1)sum +=i;}num.sum = sum;num.type = 1, num.p1 = p1, num.p2 = p2;if(c0==1 && c1==0)num.type = 2;else if(c0==2)num.type = 3;else if(c1==1 && c0==0)num.type = 4;else if(c1==1 && c0==1)num.type = 5;else if(c2==1)num.type = 6;else if(b[4] - b[0] == 4)num.type = 7;else if(b[4] - b[1] == 3 && b[1] - b[0] == 9)num.type = 8;
}int main()
{string S;int n;card* c = new card[10001];while(scanf("%d", &n)!=EOF){for(int i=0;i<n;i++){cin>>c[i].s>>S;solve(S, c[i]);}sort(c, c + n);for(int i=0;i<n;i++)cout<<c[i].s<<endl;}return 0;
}

C-签到题
1.题意:SDUQD 旁边的滨海公园有 x 条长凳。第 i 个长凳上坐着 a_i 个人。这时候又有 y 个人将来到公园,他们将选择坐在某些公园中的长凳上,那么当这 y 个人坐下后,记k = 所有椅子上的人数的最大值,那么k可能的最大值mx和最小值mn分别是多少。

Input
第一行包含一个整数 x (1 <= x <= 100) 表示公园中长椅的数目
第二行包含一个整数 y (1 <= y <= 1000) 表示有 y 个人来到公园
接下来 x 个整数 a_i (1<=a_i<=100),表示初始时公园长椅上坐着的人数

Output
输出 mn 和 mx

2.思路:首先,将现有的数组a进行排序,最大值就是让y个人全部坐在目前人最多的那个长椅上,即mx=a[n-1]+y。
然后最小值就是要让每个长椅上的人尽可能地均匀,有两种情况:
(1)当y不足以分配给其他长椅使他们的数值都达到a[n-1]时,那么最小值就是a[n-1];
(2)当y足以分配给其他长椅使他们的数值都达到a[n-1]时,先分配,即让所有的长椅的人数都达到k,然后剩下的人平均分给x个长椅,然后最多的那个即为mn.
最后依次输出mn和mx即可。

3.代码:

#include<iostream>
#include<algorithm>
using namespace std;int a[101];int main()
{int n, num, mx, mn, max1, sum;cin>>n>>num;for(int i=0;i<n;i++)cin>>a[i];sort(a, a+n);max1 = a[n-1];mn = max1 , sum = 0, mx = max1 + num;for(int i=0;i<n;i++)sum = sum + max1 - a[i];if(sum<num){sum = num - sum;mn = sum/n + mn;if(sum%n!=0)mn++;}cout<<mn<<" "<<mx;return 0;
}

Week10作业
A-签到题
1.题意:东东在玩游戏“Game23”。
在一开始他有一个数字n,他的目标是把它转换成m,在每一步操作中,他可以将n乘以2或乘以3,他可以进行任意次操作。输出将n转换成m的操作次数,如果转换不了输出-1。

Input
输入的唯一一行包括两个整数n和m(1<=n<=m<=5*10^8).

Output
输出从n转换到m的操作次数,否则输出-1.

2.题意:该问题较为简单,由题意知,转换时只能乘以2或3,故转换过程有且只有一组解。所以我们只需使用两个while循环便可求出答案。

3.代码:

#include <iostream>
using namespace std;int sum;bool judge(int m, int n)
{int s = m/n;if(m%n!=0)return false;while(s%2==0&&s!=0){sum++;s=s/2;}while(s%3==0&&s!=0){sum++;s=s/3;}if(s==1)return true;elsereturn false;
}int main()
{int m, n;cin>>m>>n;sum = 0;if(judge(n, m))cout<<sum<<endl;elsecout<<-1<<endl;return 0;
}

B-LIS&LCS
1.题意:东东有两个序列A和B。
他想要知道序列A的LIS和序列AB的LCS的长度。
注意,LIS为严格递增的,即a1<a2<…<ak(ai<=1,000,000,000)。

Input
第一行两个数n,m(1<=n<=5,000,1<=m<=5,000)
第二行n个数,表示序列A
第三行m个数,表示序列B

Output
输出一行数据ans1和ans2,分别代表序列A的LIS和序列AB的LCS的长度

2.思路:
一、
对于数组A,求解LIS的过程如下:
定义 fi 表示以 Ai 为结尾的最长上升序列的方程。
初始化时f1 = 1,转移过程如下:

LIS的长度为max{f[i], i=1…n }
此外也可以调用LCS函数来计算LIS,求出A数组和按升序排列的A数组的LCS
长度即可。
注:因为要求解的LIS为严格递增的,所以A数组排完序后需要将重复的元素覆盖掉。

二、
对于数组a, b,求解LCS 的过程如下(A的size为m, B的size为n)。
假设f[i][j] 为 a1, a2, …, ai 和 b1, b2, …, bj 的 LCS 长度
初始时f[1][0] = f[0][1] = f[0][0] = 0
当 ai == bj 时,f[i][j] = f[i-1][j-1] + 1,否则 f[i][j] = max(f[i-1][j], f[i][j-1])
然后f[m][n]的值即为LCS 的长度。

3.代码:

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;int a[5001], b[5001], c[5001];
int f[5001][5001];void LCS(int *a, int *b, int m, int n)
{f[1][0] = f[0][1] = f[0][0] = 0;for(int i=1;i<=m;i++)for(int j=1;j<=n;j++){if(a[i]==b[j])f[i][j] = f[i-1][j-1] + 1;elsef[i][j] = max(f[i-1][j], f[i][j-1]);}cout<<f[m][n];
}int main()
{int m, n;cin>>m>>n;for(int i=1;i<=m;i++){cin>>a[i];c[i] = a[i];} for(int i=1;i<=n;i++)cin>>b[i];sort(c+1, c+m+1);for(int i=1;i<=m;i++)if(c[i]==c[i-1])c[i-1]=1e9;LCS( a, c, m, m);cout<<" ";LCS( a, b, m, n);return 0;
}

C-拿数问题
1.题意:YJQ 上完第10周的程序设计思维与实践后,想到一个绝妙的主意,他对拿数问题做了一点小修改,使得这道题变成了 拿数问题 II。
给一个序列,里边有 n 个数,每一步能拿走一个数,比如拿第 i 个数, Ai = x,得到相应的分数 x,但拿掉这个 Ai 后,x+1 和 x-1 (如果有 Aj = x+1 或 Aj = x-1 存在) 就会变得不可拿(但是有 Aj = x 的话可以继续拿这个 x)。求最大分数。

Input
第一行包含一个整数 n (1 ≤ n ≤ 105),表示数字里的元素的个数
第二行包含n个整数a1, a2, …, an (1 ≤ ai ≤ 105)

Output
输出一个整数:n你能得到最大分值。

2.思路:本题与上课所讲主要是存储方式不同,对于数值x,数组a中a[x]为其出现的次数。max为x中的最大值,之后计算过程与上课讲的类似。
dp[i] , 仅考虑 A[1…i] ,能拿到的最大分数
初始时dp[0] = 0, dp[1] = a[1].
dp[i] = max(dp[i-1], dp[i-2]+a[i]*i);
然后输出dp[max1]即可。
同时因1 ≤ n ≤ 100000和1 ≤ ai ≤ 100000,故最终结果用long long int来表示。

3.代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;int a[100001];
long long int point[100001];int main()
{int n, m, sum, max1;while(scanf("%d", &n)!=EOF){memset(a, 0, sizeof(a));memset(point, 0, sizeof(point));max1 = 0;for(int i=0;i<n;i++){scanf("%d", &m);a[m]++;max1 = max(max1, m);}point[0] = 0, point[1] = a[1];for(int i=2;i<=max1;i++){long long int temp =(long long int) a[i]*i;point[i] = max(point[i-1], point[i-2]+temp);}printf("%lld\n", point[max1]);}return 0;
}

月模拟题3-炉石传说
1.题意:《炉石传说:魔兽英雄传》(Hearthstone: Heroes of Warcraft,简称炉石传说)是暴雪娱乐开发的一款集换式卡牌游戏(如下图所示)。

游戏在一个战斗棋盘上进行,由两名玩家轮流进行操作,本题所使用的炉石传说游戏的简化规则如下:
  * 玩家会控制一些角色,每个角色有自己的生命值和攻击力。当生命值小于等于 0 时,该角色死亡。角色分为英雄和随从。
  * 玩家各控制一个英雄,游戏开始时,英雄的生命值为 30,攻击力为 0。当英雄死亡时,游戏结束,英雄未死亡的一方获胜。
  * 玩家可在游戏过程中召唤随从。棋盘上每方都有 7 个可用于放置随从的空位,从左到右一字排开,被称为战场。当随从死亡时,它将被从战场上移除。
  * 游戏开始后,两位玩家轮流进行操作,每个玩家的连续一组操作称为一个回合。
  * 每个回合中,当前玩家可进行零个或者多个以下操作:
  1) 召唤随从:玩家召唤一个随从进入战场,随从具有指定的生命值和攻击力。
  2) 随从攻击:玩家控制自己的某个随从攻击对手的英雄或者某个随从。
  3) 结束回合:玩家声明自己的当前回合结束,游戏将进入对手的回合。该操作一定是一个回合的最后一个操作。
  * 当随从攻击时,攻击方和被攻击方会同时对彼此造成等同于自己攻击力的伤害。受到伤害的角色的生命值将会减少,数值等同于受到的伤害。例如,随从 X 的生命值为 HX、攻击力为 AX,随从 Y 的生命值为 HY、攻击力为 AY,如果随从 X 攻击随从 Y,则攻击发生后随从 X 的生命值变为 HX - AY,随从 Y 的生命值变为 HY - AX。攻击发生后,角色的生命值可以为负数。
  本题将给出一个游戏的过程,要求编写程序模拟该游戏过程并输出最后的局面。
  
Input
输入第一行是一个整数 n,表示操作的个数。接下来 n 行,每行描述一个操作,格式如下:
   …
  其中表示操作类型,是一个字符串,共有 3 种:summon表示召唤随从,attack表示随从攻击,end表示结束回合。这 3 种操作的具体格式如下:
  * summon :当前玩家在位置召唤一个生命值为、攻击力为的随从。其中是一个 1 到 7 的整数,表示召唤的随从出现在战场上的位置,原来该位置及右边的随从都将顺次向右移动一位。
  * attack :当前玩家的角色攻击对方的角色 。是 1 到 7 的整数,表示发起攻击的本方随从编号,是 0 到 7 的整数,表示被攻击的对方角色,0 表示攻击对方英雄,1 到 7 表示攻击对方随从的编号。
  * end:当前玩家结束本回合。
  注意:随从的编号会随着游戏的进程发生变化,当召唤一个随从时,玩家指定召唤该随从放入战场的位置,此时,原来该位置及右边的所有随从编号都会增加 1。而当一个随从死亡时,它右边的所有随从编号都会减少 1。任意时刻,战场上的随从总是从1开始连续编号。
数据规模:
  * 操作的个数0 ≤ n ≤ 1000。
  * 随从的初始生命值为 1 到 100 的整数,攻击力为 0 到 100 的整数。
  * 保证所有操作均合法,包括但不限于:
   1) 召唤随从的位置一定是合法的,即如果当前本方战场上有 m 个随从,则召唤随从的位置一定在 1 到 m + 1 之间,其中 1 表示战场最左边的位置,m + 1 表示战场最右边的位置。
   2) 当本方战场有 7 个随从时,不会再召唤新的随从。
   3) 发起攻击和被攻击的角色一定存在,发起攻击的角色攻击力大于 0。
   4) 一方英雄如果死亡,就不再会有后续操作。
数据约定:
  前 20% 的评测用例召唤随从的位置都是战场的最右边。
  前 40% 的评测用例没有 attack 操作。
  前 60% 的评测用例不会出现随从死亡的情况。
  
Output
输出共 5 行:
  第 1 行包含一个整数,表示这 n 次操作后(以下称为 T 时刻)游戏的胜负结果,1 表示先手玩家获胜,-1 表示后手玩家获胜,0 表示游戏尚未结束,还没有人获胜。
  第 2 行包含一个整数,表示 T 时刻先手玩家的英雄的生命值。
  第 3 行包含若干个整数,第一个整数 p 表示 T 时刻先手玩家在战场上存活的随从个数,之后 p 个整数,分别表示这些随从在 T 时刻的生命值(按照从左往右的顺序)。
  第 4 行和第 5 行与第 2 行和第 3 行类似,只是将玩家从先手玩家换为后手玩家。

Example
Input
8
summon 1 3 6
summon 2 4 2
end
summon 1 4 5
summon 1 2 1
attack 1 2
end
attack 1 1

12345678910
Output
0
30
1 2
30
1 2

2.思路:首先构建一个结构体,用于存储英雄和随从的攻击力和血量。利用vector数组分别存储先手和后手玩家,a[0]为先手玩家,a[1]为后手玩家。先手和后手的交换可以通过(m+1)%2或!m实现。
直接调用vector数组完成数据的插入和删除。需要注意的就是当一方英雄血量<=0时,不需要删除元素,还有就是输出的血量可能为负数。

3.代码:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <string.h>
using namespace std;struct servant
{int life, att;servant(int a, int b){life = a, att = b;}
};
vector<servant> a[2];int main()
{int n, m, num, num1, m1;int attack, life;cin>>n;//scanf("%d", &n);string s;m = 0;a[0].push_back({30, 0});a[1].push_back({30, 0});for(int i=0;i<n;i++){cin>>s;if(s=="summon"){cin>>num>>attack>>life;a[m].insert(a[m].begin()+num, {life, attack});}if(s=="attack"){cin>>num>>num1;m1 = (m+1)%2;a[m][num].life -= a[m1][num1].att;a[m1][num1].life -= a[m][num].att;if(a[m][num].life<=0&&num!=0)a[m].erase(a[m].begin()+num);if(a[m1][num1].life<=0&&num1!=0)a[m1].erase(a[m1].begin()+num1);      }if(s=="end")m = (m+1)%2;}if(a[0][0].life<=0)cout<<-1<<endl;printf("-1\n");else if(a[1][0].life<=0)cout<<1<<endl;printf("1\n");else cout<<0<<endl;printf("0\n");    cout<<a[0][0].life<<endl;printf("%d\n", a[0][0].life);cout<<a[0].size()-1<<" ";printf("%d ", a[0].size()-1);for(int i=1;i<a[0].size();i++)printf("%d ", a[0][i]);printf("\n");printf("%d\n", a[1][0].life);printf("%d ", a[1].size()-1);for(int i=1;i<a[1].size();i++)printf("%d ", a[1][i]);printf("\n");return 0;
}

月模拟题4-元素模拟器
1.题意:
2.思路:定义元素结构体element,内含标签、id、行数、级数四个属性。
文档读入时,判断其标签属性,并使用transform函数并将其全部转为小写,id属性不变,同时还要记录其行号和级数,将其存放于element类型的一个数组的中,其索引即为元素下标。
读入元素选择器,利用vector存储。
有空格则间断,标签属性全部转为小写。然后对vector中内容进行逐步查找,在查找过程中,记录下一步查找的起始行和最小级。如果是查找的最后一步,即vector中的最后一个元素,则查找到元素相等且级数大于最小级的元素存入vector中即可,即为答案。如果不是,则使用提示的贪心策略,找到层级最小的匹配项。

3.代码:

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;struct element
{string label, id;//标签、id int row;  //行int level;  //级element(string lab, string i, int rw, int lev){label = lab;id = i;row = rw;level = lev;}element(){}
}elem[101];vector<string> p;
vector<int> ans;
int n, m;void solve()
{string s;getline(cin, s, '\n');p.clear(); //清空int t = 0, tt = 0; //查找位置while (true){string str;t = s.find(" ",tt);if(t==-1)str = s.substr(tt);elsestr = s.substr(tt, t - tt); if (str[0]!='#')transform(str.begin(), str.end(), str.begin(), ::tolower);p.push_back(str);if (t == -1) break;  //不存在,退出tt = t + 1;}
}
void find()
{ans.clear();int rw = -1, lev = -1;//行数、级数 for (int i = 0; i < p.size(); i++){if (i == p.size() - 1) //最后一级{for (int j = rw + 1; j < n; j++)if ((elem[j].label == p[i] || elem[j].id == p[i]) && elem[j].level > lev)ans.push_back(elem[j].row);}else  //前几级{if (lev = -1) lev = n + 1;for (int j = rw + 1; j < n; j++)  //查找级数最低的{if ((elem[j].label == p[i] || elem[j].id == p[i]) && elem[j].level < lev){rw = j;  lev = elem[j].level; }}}}
}int main()
{cin>>n>>m; getchar();for (int i = 0; i < n; i++){string s, lab, id;getline(cin, s, '\n');int lev = 0, t = 0;while (true){t = s.find('.',lev);if (t ==-1) break;lev++;}t = s.find(" "); //查找空格if (t == -1){lab = s.substr(lev);id = " ";}else{lab = s.substr(lev, t - lev);id = s.substr(t + 1);}transform(lab.begin(), lab.end(), lab.begin(), ::tolower);//标签小写转elem[i] = element(lab, id, i+1, lev / 2);}for (int i = 0; i < m; i++){solve();find();cout<<ans.size();for(int i = 0 ; i < ans.size() ; i++)cout <<" "<< ans[i];cout << endl;}return 0;
}

Week14-猫睡觉问题
1.题意:众所周知,TT家里有一只魔法喵。这只喵十分嗜睡。一睡就没有白天黑夜。喵喵一天可以睡多次!!每次想睡多久就睡多久╭(╯^╰)╮
喵睡觉的时段是连续的,即一旦喵喵开始睡觉了,就不能被打扰,不然喵会咬人哒[○・`Д´・ ○]
可以假设喵喵必须要睡眠连续不少于 A 个小时,即一旦喵喵开始睡觉了,至少连续 A 个小时内(即A*60分钟内)不能被打扰!
现在你知道喵喵很嗜睡了,它一天的时长都在吃、喝、拉、撒、睡,换句话说要么睡要么醒着滴!
众所周知,这只魔法喵很懒,和TT一样懒,它不能连续活动超过 B 个小时。
猫主子是不用工作不用写代码滴,十分舒适,所以,它是想睡就睡滴。
但是,现在猫主子有一件感兴趣的事,就是上BiliBili网站看的新番。
新番的播放时间它已经贴在床头啦(每天都用同一张时间表哦),这段时间它必须醒着!!
作为一只喵喵,它认为安排时间是很麻烦的事情,现在请你帮它安排睡觉的时间段。

Input
多组数据,多组数据,多组数据哦,每组数据的格式如下:
第1行输入三个整数,A 和 B 和 N (1 <= A <= 24, 1 <= B <= 24, 1 <= n <= 20)
第2到N+1行为每日的新番时间表,每行一个时间段,格式形如 hh:mm-hh:mm (闭区间),这是一种时间格式,hh:mm 的范围为 00:00 到 23:59。注意一下,时间段是保证不重叠的,但是可能出现跨夜的新番,即新番的开始时间点大于结束时间点。
保证每个时间段的开始时间点和结束时间点不一样,即不可能出现类似 08:00-08:00 这种的时间段。时长的计算由于是闭区间所以也是有点坑的,比如 12:00-13:59 的时长就是 120 分钟。
不保证输入的新番时间表有序。

Output
我们知道,时间管理是一项很难的活,所以你可能没有办法安排的那么好,使得这个时间段满足喵喵的要求,即每次睡必须时间连续且不少于 A 小时,每次醒必须时间连续且不大于 B 小时,还要能看完所有的番,所以输出的第一行是 Yes 或者 No,代表是否存在满足猫猫要求的时间管理办法。
然后,对于时间管理,你只要告诉喵喵,它什么时候睡觉即可。
即第2行输出一个整数 k,代表当天有多少个时间段要睡觉
接下来 k 行是喵喵的睡觉时间段,每行一个时间段,格式形如 hh:mm-hh:mm (闭区间),这个在前面也有定义。注意一下,如果喵喵的睡眠时段跨越当天到达了明天,比如从23点50分睡到0点40分,那就输出23:50-00:40,如果从今晚23:50睡到明天早上7:30,那就输出23:50-07:30。
输出要排序吗?(输出打乱是能过的,也就是说,题目对输出的那些时间段间的顺序是没有要求的)
哦对了,喵喵告诉你说,本题是 Special Judge,如果你的输出答案和 Sample 不太一样,也可能是对的,它有一个判题程序来判定你的答案(当然,你对你自己的答案肯定也能肉眼判断)

Sample Input
12 12 1
23:00-01:00
3 4 3
07:00-08:00
11:00-11:09
19:00-19:59

Sample Output
Yes
1
01:07-22:13
No

2.思路:这个题目简单来说就是个区间检查问题,首先依次输入多个区间,然后我们再查看各个新生成的区间和原区间的情况,输出满足条件的区间。区间的输入好解决,输入之后按照时间大小先后排序即可。唯一需要注意的地方就是这应该是一个环,所以我直接将最小的时间点插入到排好序的数组中。
接下来就是检查各个区间的情况,在输入时,我将区间的起点记为1,终点记为0。所以我们每一次遍历都需要从值为1的结点开始。然后检查区间的时长,如果时长大于所允许的最大值,那么就说明无法完成编排;
还有就是清醒区间时长的计算可能不止一个区间,有可能是多个区间的和,因此我们每一次统计都需要统计到第一个可以睡觉的区间(一旦遇到,将之前的统计结果清零即可)。除此之外,就是需要注意环的问题,遍历到结尾时有可能要回到开头的。

3.代码:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
using namespace std;struct time
{int a, b, c;time(int x, int y, int status){a = x, b = y, c = status;}time(){}bool operator <(const time& t) const{if(a!=t.a)return a<t.a;else if(b!=t.b)return b<t.b;}
};bool gettime(time l, time r, int n)
{l.b += l.a*60;r.b += r.a*60;if(r.b<l.b)r.b += 24*60;if(r.b-l.b-1>=60*n)return true;return false;
}
int getsum(time l, time r)
{if(r.a<l.a)r.a +=24;r.b += (r.a - l.a)*60;return r.b-l.b+1;
}vector<time> t, sleep; int main()
{int a, b, n, x, y, sum, status, l;while(~scanf("%d %d %d", &a, &b, &n)){t.clear(), sleep.clear();status = 0;for(int i=0;i<n;i++){scanf("%d:%d-", &x, &y);time t1(x, y, 1);t.push_back(t1);scanf("%d:%d", &x, &y);time t2(x, y, 0);t.push_back(t2); }sort(t.begin(), t.end());t.push_back(t[0]);sum = 0;  for(int i=0;i<t.size();i++) {if(t[i].c&&i!=t.size()-1){sum +=getsum(t[i], t[i+1]); if(sum>b*60)status = 1;    i++;if(i+1==t.size())l = 1;elsel = i+1;if(!gettime(t[i], t[l], a))sum += getsum(t[i], t[l])-2;else{sum = 0;if(t[i].b==59){time t1(t[i].a+1, 0, 1);sleep.push_back(t1);}   else{time t1(t[i].a, t[i].b+1, 1);sleep.push_back(t1);}    if(t[l].b==0){time t2(t[l].a-1, 59, 0);if(t2.a<0)t2.a=23;sleep.push_back(t2);}        else{time t2(t[l].a, t[l].b-1, 0);sleep.push_back(t2);}}}}if(status||sleep.size()==0)printf("No\n");else{printf("Yes\n");printf("%d\n", (sleep.size()+1)/2);for(int i=0;i<sleep.size();i++){printf("%02d:%02d-%02d:%02d\n", sleep[i].a, sleep[i].b, sleep[i+1].a, sleep[i+1].b);i++;}} }
}

Week10-东东转魔方
1.题意:东东有一个二阶魔方,即2×2×2的一个立方体组。立方体由八个角组成。
魔方的每一块都用三维坐标(h, k, l)标记,其中h, k, l∈{0,1}。六个面的每一个都有四个小面,每个小面都有一个正整数。
对于每一步,东东可以选择一个特定的面,并把此面顺时针或逆时针转90度。
请你判断,是否东东可以在一个步骤还原这个魔方(每个面没有异色)。

Input
输入的第一行包含一个整数N(N≤30),这是测试用例的数量。
对于每个测试用例, 第 1~4 个数描述魔方的顶面,这是常见的2×2面,由(0,0,1),(0,1,1),(1,0,1),(1,1,1)标记。四个整数对应于上述部分。
第 5~8 个数描述前面,即(1,0,1),(1,1,1),(1,0,0),(1,1,0)的公共面。四个整数 与上述各部分相对应。
第 9~12 个数描述底面,即(1,0,0),(1,1,0),(0,0,0),(0,1,0)的公共面。四个整数与上述各部分相对应。
第 13~16 个数描述背面,即(0,0,0),(0,1,0),(0,0,1),(0,1),(0,1,1)的公共面。四个整数与上述各部分相对应。
第 17~20 个数描述左面,即(0,0,0),(0,0,1),(1,0,0),(1,0,1)的公共面。给出四个整数与上述各部分相对应。
第 21~24 个数描述了右面,即(0,1,1),(0,1,0),(1,1,1),(1,1,0)的公共面。给出四个整数与上述各部分相对应。
换句话说,每个测试用例包含24个整数a、b、c到x。你可以展开表面以获得平面图

Output
对于每个测试用例,魔方如果可以至多 “只转一步” 恢复,输出YES,则输出NO。

2.思路:本题需要在开始考虑好解题框架,否则会带来一些不必要的麻烦。由题意知,本题的魔方是一个二阶,即222的立方体组,故转的方法有:上面顺时针转90度,前面顺时针,前面逆时针,左边顺时针(相当于右边顺时针),左边逆时针(相当于左边逆时针),逆时针转,分别对不同的情况进行处理,最后按要求输出结果即可。

3.代码:

#include<iostream>
using namespace std;int a[7][5],b[7][5];void way1()   //前面逆时针
{int temp1,temp2;temp1=a[6][3];temp2=a[6][4];a[6][3]=a[1][3];a[6][4]=a[1][4];a[1][3]=a[5][3];a[1][4]=a[5][4];a[5][3]=a[3][2];a[5][4]=a[3][1];a[3][1]=temp2;a[3][2]=temp1;
}void way2()    //前面逆时针
{int temp1,temp2;temp1=a[5][3];temp2=a[5][4];a[5][3]=a[1][3];a[5][4]=a[1][4];a[1][3]=a[6][3];a[1][4]=a[6][4];a[6][3]=a[3][2];a[6][4]=a[3][1];a[3][1]=temp2;a[3][2]=temp1;
}void way3()   //上面顺时针
{int temp1,temp2;temp1=a[2][1];temp2=a[2][2];a[2][1]=a[6][3];a[2][2]=a[6][1];a[6][3]=a[4][4];a[6][1]=a[4][3];a[4][4]=a[5][2];a[4][3]=a[5][4];a[5][2]=temp1;a[5][4]=temp2;
} void way4()    //上面逆时针
{int temp1,temp2;temp1=a[2][1];temp2=a[2][2];a[2][1]=a[5][2];a[2][2]=a[5][4];a[5][2]=a[4][4];a[5][4]=a[4][3];a[4][4]=a[6][3];a[4][3]=a[6][1];a[6][1]=temp2;a[6][3]=temp1;
}void way5()    //左边顺时针
{int temp1,temp2;temp1=a[1][1];temp2=a[1][3];a[1][1]=a[4][1];a[1][3]=a[4][3];a[4][1]=a[3][1];a[4][3]=a[3][3];a[3][1]=a[2][1];a[3][3]=a[2][3];a[2][1]=temp1;a[2][3]=temp2;
} void way6()   //左边逆时针
{int temp1,temp2;temp1=a[1][1];temp2=a[1][3];a[1][1]=a[2][1];a[1][3]=a[2][3];a[2][1]=a[3][1];a[2][3]=a[3][3];a[3][1]=a[4][1];a[3][3]=a[4][3];a[4][1]=temp1;a[4][3]=temp2;
}bool judge()
{int j=0;for(int i=1;i<=6;i++){if(a[i][1]==a[i][2]&&a[i][2]==a[i][3]&&a[i][3]==a[i][4])j++;}if(j==6)return true;elsereturn false;
}int main()
{int n;cin>>n;while(n--){for(int i=1;i<=6;i++){for(int j=1;j<=4;j++){cin>>a[i][j];b[i][j]=a[i][j];}} if(judge()){cout<<"YES"<<endl;continue;}way1();if(judge()){cout<<"YES"<<endl;continue;}for(int i=1;i<=6;i++){for(int j=1;j<=4;j++)a[i][j]=b[i][j];}way2();if(judge()){cout<<"YES"<<endl;continue;}for(int i=1;i<=6;i++){for(int j=1;j<=4;j++)a[i][j]=b[i][j];}way3();if(judge()){cout<<"YES"<<endl;continue;}for(int i=1;i<=6;i++){for(int j=1;j<=4;j++)a[i][j]=b[i][j];}way4();if(judge()){cout<<"YES"<<endl;continue;}for(int i=1;i<=6;i++){for(int j=1;j<=4;j++)a[i][j]=b[i][j];}way5();if(judge()){cout<<"YES"<<endl;continue;}for(int i=1;i<=6;i++){for(int j=1;j<=4;j++)a[i][j]=b[i][j];}way6();if(judge()){cout<<"YES"<<endl;continue;}for(int i=1;i<=6;i++){for(int j=1;j<=4;j++)a[i][j]=b[i][j];}cout<<"NO"<<endl;}return 0;}

作业Week9、10+月模拟题3、4+CSP3、4+限时大模拟10、14相关推荐

  1. 考虑单用户计算机上的下列I O操作,操作系统概论自考2016年10月真题

    操作系统概论自考2016年10月真题及答案解析 本试卷为单选题型,多选,填空题,简答题,综合等题型. 一.单项选择题在每小题列出的四个备选项中只有一个是符合题目要求的,请将其代码填写在题后的括号内.错 ...

  2. 下列不属于未来发展的计算机技术是,计算机系统结构自考2017年10月真题

    计算机系统结构自考2017年10月真题及答案解析 本试卷为选择题型,填空题,简答题,应用题等题型. 一.单项选择题在每小题列出的四个备选项中只有一个是符合题目要求的,请将其代码填写在题后的括号内.错选 ...

  3. 微型计算机2013年10月下,微型计算机及接口技术2013年10月真题试题(04732)

    微型计算机及接口技术2013年10月真题试题及答案解析(04732) 微型计算机及接口技术2013年10月真题试题及答案解析(04732),本试卷总分100分. 一.单项选择题 (本大题共20小题,每 ...

  4. JAVA月数输入24回车后变成12_Java语言程序设计(一)自考2012年10月真题

    Java语言程序设计(一)自考2012年10月真题及答案解析 本试卷为单选题型,填空题,程序填空题,程序分析题,程序设计等题型. 一.单项选择题在每小题列出的四个备选项中只有一个是符合题目要求的,请将 ...

  5. 因特网上的计算机通常使用的网络协议为,计算机网络原理自考2015年10月真题

    计算机网络原理自考2015年10月真题及答案解析 本试卷为单选题型,填空题,简答,计算等题型. 一.单项选择题(本大题共24小题,每小题1分,共24分) 1.局域网LAN一般采用的传输方式为 A.&q ...

  6. 微型计算机2015年10月,微型计算机及接口技术2010年10月真题试题(04732)

    微型计算机及接口技术2010年10月真题试题及答案解析(04732) 微型计算机及接口技术2010年10月真题试题及答案解析(04732),本试卷总分100分. 一.单项选择题 (本大题共20小题,每 ...

  7. 计算机网络llc是什么,计算机网络原理自考2015年10月真题

    计算机网络原理自考2015年10月真题及答案解析 本试卷为单选题型,填空题,简答,计算等题型. 一.单项选择题(本大题共24小题,每小题1分,共24分) 1.局域网LAN一般采用的传输方式为 A.&q ...

  8. c语言中int是高级语言,高级语言程序设计(一)2010年10月真题

    高级语言程序设计(一)2010年10月真题及答案解析 高级语言程序设计(一)2010年10月真题及答案,该试卷为高级语言程序设计(一)自考历年真题试卷,包含答案及详细解析. 一.单项选择题(本大题共1 ...

  9. 微型计算机2009,微型计算机及接口技术2009年10月真题试题(04732)

    微型计算机及接口技术2009年10月真题试题及答案解析(04732) 微型计算机及接口技术2009年10月真题试题及答案解析(04732),本试卷总分100分. 一.单项选择题 (本大题共20小题,每 ...

  10. 热血江湖服务器维护时间,热血江湖2016年10月8日停机更新维护公告 喜庆大烟花套餐国庆上架...

    热血江湖2016年10月8日停机更新维护公告 喜庆大烟花套餐国庆上架 尊敬的热血江湖广大玩家: 为保证服务器的稳定运行,提高游戏品质,我们将于2016年10月8日(周六)6:00-16:00对所有服务 ...

最新文章

  1. private 的访问权限
  2. %fplot('Untitled1',[-1,2])画图
  3. vs2013 乱码问题
  4. linux内核参数优化 for 高并发服务器
  5. NYOJ--517--最小公倍数(大数打表)
  6. Spring如何优雅地发送异步发送通知?
  7. python---之os.path.splitext(“文件路径”)
  8. 使用jq工具在Shell命令行处理JSON数据
  9. Windows Phone 8.1中AppBarToggleButton的绑定问题
  10. python批量打印word_Python操作Word批量生成文章的方法
  11. 职场解释系:张三丰的接班人计划
  12. 计算机网络和internet选项,大师为你详解win10系统设置Internet选项的处理
  13. Java中打印程序执行的开始时间和结束时间
  14. 计算机输入法如何显示在桌面快捷方式,电脑桌面输入法图标不见了怎么办
  15. 介绍几个好用的小软件
  16. PARALYSIS AS “SPIRITUAL LIBERATION” IN JOYCE’S DUBLINERS Iven Lucas Heister, B.A.【翻译】
  17. 2015最具成长性、发展力的创新互联网公司100佳
  18. 解决win11系统“Adobe creative cloud无法卸载”的问题
  19. Coding and Paper Letter(二十八)
  20. 职员信息管理系统php,员工信息管理系统(含附源代码).doc

热门文章

  1. LINUX 删除redis的key
  2. CSS中的span样式对齐
  3. 7-2 奥运排行榜(编程题)
  4. 1 奥运排行榜 (25分)
  5. 大二学生《web课程设计》中华英雄人物介绍袁隆平HTML+CSS+JavaScript(期末考核大作业)
  6. 北京交通大学计算机科学考研,北京交通大学2020计算机专业考研数据分析
  7. 机器学习分类简单介绍
  8. 实例域与局部变java量_Java核心技术——第4章
  9. 科研—画图图片处理2(关于photoshop)
  10. Python语言之文件操作详解(open、close、write、read、readline、readlines等)