解题报告见 Issues: (https://github.com/cc98/PAT/issues)
goby / pat Goto Github PK
View Code? Open in Web Editor NEWhttp://pat.zju.edu.cn/
http://pat.zju.edu.cn/
解题报告见 Issues: (https://github.com/cc98/PAT/issues)
水题三连击,主要是理清两个数列的游标增长规则
int main() {
vector<long> firstArray, secondArray;
long tmp, cur;
DRI(N);
REP(i, N){
scanf("%ld", &tmp);
firstArray.push_back(tmp);
}
DRI(M);
REP(i, M){
scanf("%ld", &tmp);
secondArray.push_back(tmp);
}
tmp = (N + M - 1)/2;
for (int i = 0, j = 0; tmp >= 0; tmp--) {
if(j < M && (i == N || firstArray[i] > secondArray[j])) {
cur = secondArray[j];
j++;
}
else {
cur = firstArray[i];
i++;
}
}
printf("%ld", cur);
}
排名,主要是利用sort方法吧, 当时我怎么用了那么多数组来着,一般用个 vector 加上一个 table[SIZE] 记录对应id在vector中的位置即可(索引)
又一道恶心的模拟题……比之前的银行排队又难了一点,主要是里头是有VIP桌子。
规则如下:
#define SIZE 101
#define GETTIME(H, M, S) ((H)*3600+(M)*60+(S))
#define CLOSETIME 21*3600
typedef struct _player {
int arrriveTime;
int playTime;
int isVIP;
} Player;
bool cmp(Player left, Player right){
return left.arrriveTime < right.arrriveTime;
}
vector<Player> playerList;
int availableTime[SIZE] = {0};
bool table[SIZE] = {0};
int serveCount[SIZE] = {0};
void to_time(int value, int& hh, int& mm, int& ss){
hh = value / 3600;
mm = (value % 3600)/60;
ss = value % 60;
}
void println(int arriveTime, int startTime){
int hh, mm, ss;
to_time(arriveTime, hh, mm, ss);
printf("%02d:%02d:%02d ", hh, mm, ss);
to_time(startTime, hh, mm, ss);
printf("%02d:%02d:%02d ", hh, mm, ss);
printf("%d\n", ((startTime-arriveTime)+30)/60);
}
// 把指定时间内的VIP提前
void reorderPlayerList(int startIndex, int totalPlayer, int beforeTime){
REPP(i, startIndex+1, totalPlayer){
if(playerList[i].isVIP && playerList[i].arrriveTime <= beforeTime){
Player tmp = playerList[i];
for(int k = i; k> startIndex; k--)
playerList[k]=playerList[k-1];
playerList[startIndex]=tmp;
return;
}
}
}
int main() {
int hh, mm, ss, playTime, vip;
DRI(N);
REP(i, N){
Player p;
scanf("%d:%d:%d %d %d", &hh, &mm, &ss, &playTime, &vip);
p.arrriveTime = GETTIME(hh, mm, ss);
p.playTime=(playTime > 120 ? 120 : playTime) * 60;
p.isVIP=vip;
playerList.push_back(p);
}
sort(ALL(playerList), cmp);
DRII(K, M);
REP(i, M){
DRI(tmp);
table[tmp-1] = true;
}
REP(i, N){
if(playerList[i].arrriveTime >= CLOSETIME)
break;
int availIndex=-1, vipIndex=-1;
REP(k, K){
if(availableTime[k] < playerList[i].arrriveTime){
availIndex=k;
break;
}
}
REP(k, K){
if(table[k] && availableTime[k] < playerList[i].arrriveTime){
vipIndex=k;
break;
}
}
// 有空桌
if(availIndex >= 0){
if(playerList[i].isVIP && vipIndex >= 0)
availIndex=vipIndex;
serveCount[availIndex]++;
availableTime[availIndex]=playerList[i].arrriveTime+playerList[i].playTime;
println(playerList[i].arrriveTime, playerList[i].arrriveTime);
}
else{
// 没有空桌,寻找最近一张可用桌
int ealist=CLOSETIME;
REP(k, K){
if(availableTime[k] < ealist){
ealist=availableTime[k];
availIndex=k;
}
}
if(availIndex < 0)
break;
// 如果当前为VIP桌,看看有没有要插队的VIP
if(table[availIndex] && (!playerList[i].isVIP))
reorderPlayerList(i, N, availableTime[availIndex]);
serveCount[availIndex]++;
println(playerList[i].arrriveTime, availableTime[availIndex]);
availableTime[availIndex]+=playerList[i].playTime;
}
}
printf("%d", serveCount[0]);
REPP(i, 1, K){
printf(" %d", serveCount[i]);
}
return 0;
}
求图的割点,主要是用DFS求割点
#define SIZE 1001
vector<int> adjs[SIZE];
bool marked[SIZE];
void DFS(int x) {
int size=adjs[x].size();
marked[x]=true;
REP(i,size){
if(adjs[x][i] != 0 && !marked[adjs[x][i]])
DFS(adjs[x][i]);
}
}
int main() {
DRIII(N,M,K);
REP(i,M) {
DRII(v,u);
adjs[v].push_back(u);
adjs[u].push_back(v);
}
REP(i,K) {
DRI(city);
int num=0;
MS0(marked);
marked[city] = true;
REP(i,N+1) {
if(!marked[i+1]) {
num++;
DFS(i+1);
}
}
printf("%d\n", num > 1 ? num-2:0);
}
return 0;
}
水题,主要要清楚U型的排列规则
int main() {
char arr[81];
RS(arr);
int len = LEN(arr);
int n1 = (len+2)/3 - 1;
int spacewidth=n1 > 0 ? len-2*n1 - 2 : 0;
REP(i, n1){
printf("%c", arr[i]);
REP(j, spacewidth) printf(" ");
printf("%c\n", arr[len - 1 - i]);
}
REPP(i, n1, len - n1) printf("%c", arr[i]);
return 0;
}
水题,弄个
char* dict[] = {"zero","one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
字典就ok了
水题
一棵树中求树最高的时候的根ID。
基本就是DFS求最深深度,有一种优化思路,就是当某一个节点P的相邻节点如果不在P的最深路径上面,那么这些节点的深度就是Height(P)+1,但是考试时间比较短所以直接暴力了
#define SIZE 10001
vector<int> *adj;
bool visited[SIZE];
int dfs(int start) {
visited[start] = true;
int size = adj[start].size();
int max = 0, ret;
REP(i, size){
if(!visited[adj[start][i]]){
ret = dfs(adj[start][i]);
if(max < ret)
max = ret;
}
}
return max + 1;
}
int main() {
DRI(N);
adj = new vector<int>[N+1];
REP(i, N-1){
DRII(f, t);
adj[f].push_back(t);
adj[t].push_back(f);
}
int component = 0;
int max = 0, ret;
vector<int> result;
REPP(i, 1, N+1){
if(!visited[i]){
component++;
dfs(i);
}
}
if(component == 1){
REPP(i, 1, N+1){
MS0(visited);
ret = dfs(i);
if(ret > max) {
max = ret;
result.clear();
result.push_back(i);
}
else if(ret == max) {
result.push_back(i);
}
}
int size = result.size();
REP(j, size){
printf("%d\n", result[j]);
}
}
else {
printf("Error: %d components", component);
}
return 0;
}
...
就是求最大连续子串之和,顺便把开始结束位置记录一下
当时数据结构的课已经过去4年了,做这个题目搞死我,不然就是个水题而已
要是当时我去考试肯定被搞死……略悲伤
int main()
{
// max = [sum, start, end]
int max[3] = {0},sum=0,start=-1,end;
int n0; // first input integer
bool first=true;
max[0] = -1;
CASET{
DRI(num);
// 截止到当前
end=num;
sum += num;
// 第一个数
if(first) {n0=start=num;first=false;}
// 若前面之和作废,重置初始值
if(!start)start=num;
// 更新最大值
if(sum > max[0]){max[0]=sum;max[1]=start;max[2]=end;}
// 重置和
if(sum <= 0){sum=0;start=0;}
}
if(max[0]<0){max[0]=0;max[1] = n0;max[2]=end;}
printf("%d %d %d",max[0],max[1],max[2]);
return 0;
}
有点绕的水题
bool IsPrime(int x){
int up=sqrt(x)+1;
if(x < 2) return false;
REPP(i,2,up) if(x % i == 0) return false;
return true;
}
int CalReverse(int x, int radix) {
int i = 0,result = 0;
while(x != 0){
num[i++]=x%radix+'0';
x = x / radix;
}
num[i]=0;
i=0;
while(num[i]){
result *= radix;
result += num[i]-'0';
i++;
}
return result;
}
int main() {
int n, radix;
while(1){
RI(n);
if(n<0) break;
RI(radix);
if(IsPrime(n) && IsPrime(CalReverse(n, radix)))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
大坑题,完全没有交代清楚 PAT里超多这种题目...
关系没理清,所以每次遇到这种题目都是N多的判断语句...
二分法子分支的进入也搞了我很久...为了求符合结果的最小值,所以:
LLONG cal(char* str, LLONG radix)
{
LLONG a = 0;
REPC(i,str[i]=='\0'){
int value = (str[i] >= 'a') ? (str[i]-'a'+10):(str[i]-'0');
if(value >= radix) return -1;
a *= radix;
a += value;
}
return a;
}
LLONG bfs(LLONG value, char* target, LLONG start, LLONG end){
if(start == end) return 0;
LLONG center = start + (end-start+1) / 2;
LLONG s = cal(target, start);
LLONG c = cal(target, center);
LLONG e = cal(target, end);
if(e<value || s > value) return 0;
if(s==value) return start;
if(center!=end&&c==e)
return bfs(value, target, start, center);
if(value==c) return center;
if(center==end) return 0;
if(value<c) return bfs(value, target, start, center);
return bfs(value, target, center, end);
}
int main()
{
char A[11],B[11],*c,*d;
LLONG a = 0,result=0;
RS(A);
RS(B);
DRII(tag,radix);
if(tag==1){
c=A;d=B;
}
else{
c=B;d=A;
}
if(cal(c,37) * cal(d,37)==1) result = 2;
else if(strcmp(c,d)==0) result=radix;
else if((a=cal(c,radix))>=0){
REP(i,37){
if(cal(d,i)==a) {result=i;break;}
}
if(!result) result=bfs(a,d,2,a>36?a:36);
}
if(result)printf("%lld",result);
else printf("Impossible");
return 0;
}
水题
幂最大才1000,乘的话只需要开个2_1000的空间记录每个幂上面的系数即可。系数计算就是 N_M的复杂度了。
妈蛋题目看错结果这题纠结了1个月
本题重点在于Dijkstra,以及全部最短路径保存和最后DFS(计算最短路径数+获得最优解)
这题的主要难度在于K 最大可能到100,N最多有10位,如果按最大可能,最后可能有110位,所以需要用字符处理数字。
PAT这是第二道用字符处理数字的题目了。
水题Num2
算最小的时间和最大的时间
对于进制考察比较全面的题目,判断用K进制表示翻转之后与原来的是否一致, 翻转直接用循环即可, 输出就需要借助递归完成了。
void print(int n, int radix){
if (n < radix) {
printf("%d", n);
return;
}
print(n/radix, radix);
printf(" %d", n % radix);
}
int main() {
DRII(N, radix);
int res=0, ori=N;
while (ori) {
res *= radix;
res += ori % radix;
ori /= radix;
}
printf("%s\n", res==N ? "Yes" : "No");
print(N, radix);
return 0;
}
又一道水题,主要是认真看排列规则就行了
typedef struct {
int id;
char name[10];
int score;
} Student;
template <int i>
bool cmp(Student left, Student right){
if(i == 0)
return left.id < right.id;
if(i == 1) {
int res = strcmp(left.name, right.name);
if(res == 0)
return left.id < right.id;
return res < 0;
}
else {
if(left.score == right.score)
return left.id < right.id;
return left.score < right.score;
}
}
vector<Student> students;
int main() {
DRII(N, C);
REP(i, N){
Student s;
cin >> s.id >> s.name >> s.score;
students.push_back(s);
}
switch (C) {
case 1:
sort(ALL(students),cmp<0>);
break;
case 2:
sort(ALL(students),cmp<1>);
break;
case 3:
sort(ALL(students),cmp<2>);
break;
default:
break;
}
for (auto it = students.begin(); it != students.end(); it++)
printf("%06d %s %d\n", it->id, it->name, it->score);
}
这题因为没主意看题意结果提交好几次错误
这题应该是比较简单,只是比较繁复,可能是数量比较少+STL的缘故把。
just now
7 days ago ...
a month ago ...
终于AC了……这种题目真的是有一点没想到就基本很难想得到...
代码也改了好多次,改得乱七八糟的。
原来一直没想明白,只是觉得要么只送出要么只收回,后来才恍然大悟发现不能走回头路!!!!!!!!!就是如果第一个站缺10辆,不管后来的多出了多少辆,肯定要先送出10辆...
思路理清了就是 Dijsktra + DFS 经典组合
#define SIZE 501
int dd[SIZE][SIZE]; // 距离关系
int cc[SIZE]; // 车辆数量
vector<int> pred[SIZE]; // 前驱点列表
vector<int> dist;
bool visited[SIZE];
int route[SIZE], tmpRoute[SIZE]; // 路径记录
int length = SIZE; // 路径长度
int Cmax; // 每个站最大容量
int sendTo=INT_MAX, takeBack=INT_MAX; // 送出和送回的数量
void dfs(int start,int end, int level){
tmpRoute[level] = end;
if(start == end){
// 一堆涂改变量
int m = 0, tmp = 0, perfect = Cmax / 2, st, tb, totalCount = 0;
RREP(i,level){
totalCount += cc[tmpRoute[i]];
// 从开始获取缺少的车辆,发现缺车辆,记录并重置tmp
tmp += cc[tmpRoute[i]] - perfect;
if(tmp < 0) { m -= tmp;tmp = 0; }
}
// 送出
st = m;
// 送回
tb = totalCount + st - level * (Cmax/2);
if(st < sendTo || (st == sendTo && tb < takeBack)){
sendTo = st;
takeBack = tb;
memcpy(route, tmpRoute, level*sizeof(int));
length = level;
}
return;
}
int size = pred[end].size();
REP(i, size){
dfs(start, pred[end][i], level+1);
}
}
int main()
{
int c0, c1, d, tmp;
RI(Cmax);
DRI(N);
DRII(target, M);
MS1(dd);
MS1(cc);
MS1(route);
dist.assign(N + 1, INT_MAX);
cc[0]=0;
REP(i, N){
RI(tmp);
cc[i+1]=tmp;
}
REP(i, M){
RIII(c0, c1, d);
dd[c0][c1]=dd[c1][c0]=d;
}
dist[0] = 0;
while (true) {
int u = -1;
int m = INT_MAX;
REP(i, N+1){
if(!visited[i] && m > dist[i]){
u = i;
m = dist[i];
}
}
if(u == -1) break;
visited[u] = true;
REP(i, N+1){
if(i != u && dd[i][u] >= 0){
long len = dd[i][u];
len += dist[u];
if(len < dist[i]){
dist[i] = len;
pred[i].clear();
pred[i].push_back(u);
}
else if(len == dist[i]){
pred[i].push_back(u);
}
}
}
}
dfs(0, target, 0);
printf("%d 0", sendTo);
while(length--){
printf("->%d", route[length]);
}
printf(" %d", takeBack);
return 0;
}
AC了饿
想法是这样纯贪心策略:
车加满油最多走 MaxRunning 的路,那么:
到第K个站的时候( K = 0, 1, 2, ... , N - 1) :
差不多就这样,搞死我了
struct station{
double price;
double location;
};
bool cmp(station left, station right){
return left.location < right.location;
}
int main() {
vector<station> stations;
double Cmax, D, Davg, N;
station s;
scanf("%lf%lf%lf%lf", &Cmax, &D, &Davg, &N);
REP(i, N){
scanf("%lf%lf", &s.price, &s.location);
stations.push_back(s);
}
sort(ALL(stations), cmp);
int cur = 0;
double runDis = Cmax * Davg, total = 0, amount = 0, available = 0;
while (cur < N) {
// 找到目标或者无法到达
if(total >= D || total < stations[cur].location) break;
// 寻找下一个站点
int min = -1;
for(int i = cur + 1;i < N
&& stations[i].location - stations[cur].location <= runDis; i++) {
if(min == -1 || stations[i].price < stations[min].price)
min = i;
if(stations[min].price < stations[cur].price)
break;
}
double needAdd = 0, cost = 0;
if(min == -1) { // 1). 找不到
if(total + runDis > D)
cost = (D - total) / Davg; // 目标在可达范围内
else
cost = Cmax; // 可达范围外
needAdd = cost - available;
total += cost * Davg;
min = cur + 1;
}
else if(stations[min].location >= D){ // 2). 在目标里程之外,开到目标即可
cost = (D - total) / Davg;
needAdd = cost - available;
total = D;
}
else if(stations[min].price > stations[cur].price) { // 3). 比当前价格高,经过加尽量少得油
if(total + runDis >= D) { // 目标可达,直接行驶到目标
cost = (D - total) / Davg;
needAdd = cost - available;
total = D;
}
else { // 否则加满油
cost = (stations[min].location - total) / Davg;
needAdd = Cmax - available;
total = stations[min].location;
}
}
else { // 4). 比当前小,加到刚好开到最小的站即可(分支2排除这里头直接到达目标的可能)
cost = (stations[min].location - total) / Davg;
needAdd = cost - available;
total = stations[min].location;
}
available = available + needAdd - cost;
amount += needAdd * stations[cur].price;
cur = min;
}
if(total < D) printf("The maximum travel distance = %.2lf", total);
else printf("%.2lf", amount);
return 0;
}
双重权值的Dijkstra题目 感觉这期题目难度降了0.5-1.0
#define SIZE 501
int dd[SIZE][SIZE];
int cc[SIZE][SIZE];
int pred[SIZE];
vector<int> dist;
vector<long> cost;
bool visited[SIZE];
int route[SIZE];
int max = 0;
int main() {
int c0, c1, d, c;
DRII(N, M);
DRII(start, end);
MS1(dd);
MS1(cc);
MS1(route);
MS1(pred);
dist.assign(N, INT_MAX);
cost.assign(N, INT_MAX);
REP(i, M){
RII(c0, c1);
RII(d, c);
dd[c0][c1]=dd[c1][c0]=d;
cc[c0][c1]=cc[c1][c0]=c;
}
dist[start] = 0;
cost[start] = 0;
while (true) {
int u = -1;
int m = INT_MAX;
REP(i, N){
if(!visited[i] && m > dist[i]){
u = i;
m = dist[i];
}
}
if(u == -1) break;
visited[u] = true;
REP(i, N){
if(i != u && dd[i][u] >= 0){
long len = dd[i][u];
len += dist[u];
long cst = cc[i][u];
cst += cost[u];
if(len < dist[i]){
dist[i] = len;
pred[i] = u;
cost[i] = cst;
}
else if(len == dist[i]){
if(cst < cost[i]){
cost[i]=cst;
pred[i] = u;
}
}
}
}
}
int len = 0, cur = pred[end];
while (cur != start) {
route[len++]=cur;
cur=pred[cur];
}
printf("%d", start);
while (len) {
printf(" %d", route[--len]);
}
printf(" %d", end);
printf(" %d %d", dist[end], cost[end]);
return 0;
}
水题
根据后序遍历Post[]、中序遍历输出前序In[],原来的办法是想能不能直接比较Post、In两个数组得到前序,发现不行。只好乖乖地还原树了。
根据中序和后序遍历的特点,后序遍历的话父节点总在最后面的,对于中序遍历,则父节点在中间;因此对于:
Post[k], Post[k+1], Post[k+2], ... Post[k+N]
In[j], In[j+1], In[j+2] ... In[j+N]
当前的子树的根节点为Post[k+N], 假设In[j+p] == Post[k+N], 那么当前树的左子树为:Post[k], Post[k+1] ... Post[k+p-1] 和 In[j], In[j+1] ... In[j+p-1];
右子树为: Post[k+p], Post[k+p+1] ... Post[k+N-1] 和 In[j+p+1], In[j+p+2], ... , In[j+N]。
所以下一次迭代为:
Left: k = k, j = j, len = p - 1
Right: k = k+p, j = j + p + 1, len = N - p - 1
vector<int> post;
vector<int> in;
typedef struct _node node;
struct _node {
int value;
node* left;
node* right;
};
queue<node*> result;
/// ps: postorder starting index;
/// is: inorder starting index
node* dfs(int ps, int is, int len){
int value = post[ps + len -1];
int pivot=is;
node * n = new node;
n->left=n->right=NULL;
n->value = value;
REPP(i, is, is+len){
if(in[i]==value){
pivot=i-is;
break;
}
}
if(pivot > 0) n->left = dfs(ps, is, pivot);
if(len > pivot+1) n->right = dfs(ps+pivot, pivot+is+1 , len - pivot - 1);
return n;
}
int main()
{
DRI(N);
REP(i,N){DRI(x);post.push_back(x);}
REP(i,N){DRI(x);in.push_back(x);}
node *tree = dfs(0,0, N);
bool flag=true;
result.push(tree);
while (!result.empty()) {
node* value=result.front();
result.pop();
if(flag) {printf("%d", value->value); flag=false;}
else printf(" %d", value->value);
if(value->left) result.push(value->left);
if(value->right) result.push(value->right);
}
return 0;
}
给出一堆电话拨打记录,求订单
// 价格
int rate[24];
// 通话记录
typedef struct _record{
char name[21];
int time[3];
bool flag;
}record;
bool cmp(record l, record r){
int value = strcmp(l.name, r.name);
if(value==0)
return l.time[0]*24*60+l.time[1]*60+l.time[2] < r.time[0]*24*60+r.time[1]*60+r.time[2];
return value < 0;
}
// 计算通话费用
int cost(record &re){
int result = 0;
REP(i, re.time[1]){
result += rate[i]*60;
}
result += rate[re.time[1]]*re.time[2];
REP(i, 24){
result += (rate[i]*60)*(re.time[0]-1);
}
return result;
}
int diff(record &l, record &r){
return l.time[0]*24*60+l.time[1]*60+l.time[2] - (r.time[0]*24*60+r.time[1]*60+r.time[2]);
}
int main()
{
int month;
float sum = 0;
char prename[9]={0};
char hang[9];
vector<record> records;
REP(i,24) RI(rate[i]);
CASET{
record *r = new record;
RS(r->name);
scanf("%d:%d:%d:%d", &month, r->time, r->time+1, r->time+2);
RS(hang);
r->flag = hang[1]=='n';
records.push_back(*r);
}
sort(ALL(records), cmp);
int size=records.size();
REP(i, size-1){
record on =records[i], off=records[i+1];
if(on.flag && !off.flag && (strcmp(on.name, off.name)==0)){
if(strcmp(prename, on.name)!=0){
strcpy(prename, on.name);
if(sum) printf("Total amount: $%.2f\n", sum);
printf("%s %02d\n", prename, month);
sum = 0;
}
float tmp = (cost(off)-cost(on))/100.0;
sum+=tmp;
printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n", on.time[0],on.time[1],on.time[2],
off.time[0],off.time[1],off.time[2],diff(off, on), tmp);
}
}
if(sum) printf("Total amount: $%.2f\n", sum);
return 0;
}
模拟题, 大坑题
模拟题完全不行啊怎么办啊,坑题表现在一些结果判定上没有写清楚
我这里用了数组来表示队列,用一个游标指代当前队列的头
模拟的时候根据时间来的
#define SIZE 1001
#define TOTALTIME 541
int win[20][10]; // 窗口队列
int pw[20];
int tt[20];
int dealTime[SIZE];
int main()
{
DRII(N,M);
DRII(K,Q);
int p=0, max=0;
int cost[SIZE];
int query[SIZE];
// 此处记录最大处理时间
REP(i, K) {RI(cost[i]); if(cost[i] > max) max= cost[i];}
REP(i, Q) RI(query[i]);
MS0(pw);
MS0(tt);
MS1(dealTime);
// 先将N个人入列
REP(i,N*M){
if(i>K) break;
win[i%N][i/N]=i;
if(!tt[i%N]) tt[i%N] = cost[i];
p=i+1;
}
// 此处是按照时间来模拟的,轮询
REP(i, TOTALTIME+max){
REP(j, N){
// tt[] 为窗口的处理结束时间, pw[]为窗口指针指向第几个处理者
// dealTime为处理时间
if(tt[j] == i && win[j][pw[j]] >= 0 && dealTime[win[j][pw[j]]] < 0){
dealTime[win[j][pw[j]]]=i-cost[win[j][pw[j]]];//save deal time
if(p < K) win[j][pw[j]]=p++;
else win[j][pw[j]]=-1; //表示没有人了
pw[j]++;//deal nxt one & add time to observe
pw[j]=pw[j]%M;
tt[j]+=cost[win[j][pw[j]]];
}
}
}
REP(i, Q){
if(dealTime[query[i]-1] >= 0 && dealTime[query[i]-1] < TOTALTIME - 1){
int t=dealTime[query[i]-1]+cost[query[i]-1];
printf("%02d:%02d\n",(t/60+8),t%60);
}
else printf("Sorry\n");
}
return 0;
}
又一道模拟题
之前一道银行排队的变种,但这里每个窗口的Cache只有1,所以应该相对来说简单一些。这次以顾客的身份来解题。
// Customer
typedef struct _t{
int arrive;
int process;
}cst;
bool cmp(cst l, cst r) {
return l.arrive < r.arrive;
}
const int ftime=540*60+1;
int main() {
DRII(N,K);
int p=0, total = 0;
vector<cst> all;
REP(i, N){
int h,m,s;
scanf("%d:%d:%d", &h, &m, &s);
cst *t = new cst;
t->arrive =(h - 8)*3600+m*60+s;
DRI(process);
t->process=process*60;
all.push_back(*t);
}
sort(ALL(all), cmp);
priority_queue<int, vector<int>,greater<int>> pq;
REP(i, K) pq.push(0);
while(p < N && all[p].arrive < ftime){
int top = pq.top();
pq.pop();
if(top < all[p].arrive) top = all[p].arrive;/*IMPORTANT*/
total += top - all[p].arrive;
top += all[p].process;
pq.push(top);
p++;
}
if(p) printf("%.1f", total * 1.0 / 60 / p);
else printf("0.0");
return 0;
}
比较简单的题目,sort搞定。坑主要在排名规则。
大水题...
char dict[]={'0','1','2','3','4','5','6','7','8','9','A','B','C'};
int main() {
DRIII(r,g,b);
printf("#");
printf("%c%c", dict[r/13], dict[r%13]);
printf("%c%c", dict[g/13], dict[g%13]);
printf("%c%c", dict[b/13], dict[b%13]);
return 0;
}
这题和寻找树中两个节点的共同祖先是一个道理,而且更简单一些。
简单来说就是找到完整地两条链。不知之前怎么做的还OT过几次。
#define SIZE 100000
int tnext[SIZE];
int main() {
DRIII(fst, snd,N);
int cur, nxt;
char c;
MS1(tnext);
REP(i, N){
scanf("%d %c %d", &cur, &c, &nxt);
tnext[cur] = nxt;
}
int len1 = 0, len2 = 0;
cur = fst;
while(cur >= 0){
cur = tnext[cur];
len1++;
}
cur = snd;
while(cur >= 0){
cur = tnext[cur];
len2++;
}
if(len1 > len2){
while(len1 != len2){
fst = tnext[fst];
len1--;
}
}
else if(len1 < len2){
while(len1 != len2){
snd = tnext[snd];
len2--;
}
}
while (fst != snd) {
snd = tnext[snd];
fst = tnext[fst];
}
if(fst >= 0) printf("%05d", fst);
else printf("%d", fst);
return 0;
}
一看题目是N < 100感觉直接暴力申请个100*100的关系矩阵。
数树叶,差不多就是BFS,我BFS一般都用一个Queue搞定,结果上次参加微策略笔试,这题估计我用一个Queue被改卷老师鄙视了……没办法,这么非主流,早知道用两个Queue了。
根据输入, ParentID ChildrenNum ChildID ChildID .. ChildID
, 也就是说,ParentID 未出现过的就是叶子节点,所以弄了个数组 nonleave[] 保存非子节点,减少遍历次数。
int main()
{
// 前四个为涂改变量,最后为叶子总数
int father,childnum, child, levelcount=0, total=0;
queue<int> qq; // BFS
bool isdescendant[SIZE]; // 是否为先祖
bool nonleave[SIZE]; // 是否有后代
bool first=true;
MS0(relative);
MS0(nonleave);
MS0(isdescendant);
DRII(N,M);
REP(i, M){
RII(father, childnum);
nonleave[father]=true;
REP(j, childnum){
RI(child);
relative[father][child]=true;
isdescendant[child]=true;
}
}
total = N - M;
// BFS开始,将所有先祖扔进去
REP(i, N){
if(!isdescendant[i+1]){
qq.push(i+1);
if(!nonleave[i+1])
levelcount++;
}
}
// 在每一层ID之间添加负数的叶子树作为分隔符
qq.push(-levelcount);
levelcount=0;
while (!qq.empty() && total) {
int cur=qq.front();
qq.pop();
// 遍历查找后代节点
if(cur > 0 && nonleave[cur]){
REP(i, N){
if(relative[cur][i+1]) {
qq.push(i+1);
if(!nonleave[i+1])
levelcount++;
}
}
}
else if(cur <= 0){
// 一层结束输出个数
qq.push(-levelcount);
total += cur;
if(!first) printf(" %d", -cur);
else {printf("%d", -cur);first=false;}
levelcount=0;
}
}
return 0;
}
...
没做二连击
考试前夕试着搞定这道题
发现是图,可能需要符号表,就用了个 char[] --> int, vector 和 int[] 搞定对应关系,接下来都是对映射之后的数字进行计算。
基本思路就是:从图中得到连通分量N,从中挑选出权值大于K的子图, 计算其中权重最高的节点和节点个数,并对结果进行排序。
第一次提交获得了 1WA 1SF的结果,隐藏的坑是同一个权值输入时可以分次输入, 再提交WA不见了, SF依旧在,不知道是哪个下标越界了。
const int SIZE = 26 * 26 * 26 + 1;
int SymbolTable[SIZE];
int relation[1001][1001];
int gangCal[1001];
bool marked[1001];
vector<int> Symbol;
int memberCount;
int gangAmount;
int str2i(char str[]){
int result = 0;
for(int i = 0; i < 3; i++){
result *= 26;
result += str[i] - 'A';
}
return result;
}
void dfs(int n){
marked[n] = true;
REP(i, memberCount){
if(relation[n][i]){
gangCal[n] += relation[n][i];
gangCal[i] += relation[n][i];
gangAmount += relation[n][i];
if(!marked[i])
dfs(i);
}
}
}
/// 结果排序用
bool cmp(const pair<int, int>& left, const pair<int, int>& right){
return Symbol[left.first] < Symbol[right.first];
}
int main() {
char nameA[4], nameB[4];
int talktime, tmp, indexA, indexB;
vector<pair<int, int>> result;
DRII(N, K);
MS1(SymbolTable);
MS0(relation);
while (N--) {
scanf("%s %s %d", nameA, nameB, &talktime);
indexA = SymbolTable[str2i(nameA)];
indexB = SymbolTable[str2i(nameB)];
if(indexA < 0) {
tmp = str2i(nameA);
indexA = Symbol.size();
SymbolTable[str2i(nameA)]=indexA;
Symbol.push_back(tmp);
}
if(indexB < 0) {
tmp = str2i(nameB);
indexB = Symbol.size();
SymbolTable[str2i(nameB)]=indexB;
Symbol.push_back(tmp);
}
relation[indexA][indexB] += talktime;
}
memberCount = Symbol.size();
MS0(marked);
REP(i, memberCount){
if(!marked[i]){
gangAmount = 0;
MS0(gangCal);
dfs(i);
if(gangAmount > K){
int cnt = 0, maxindex = i;
REP(j, memberCount){
if(gangCal[j]){
cnt++;
if(gangCal[j] > gangCal[maxindex])
maxindex = j;
}
}
if(cnt > 2){
result.push_back(MP(maxindex, cnt));
}
}
}
}
sort(ALL(result), cmp);
int size = result.size();
printf("%d\n", size);
REP(i, size){
int value = Symbol[result[i].first];
nameA[0] = value / (26 * 26) + 'A';
nameA[1] = value / 26 % 26 + 'A';
nameA[2] = value % 26 + 'A';
nameA[3] = 0;
printf("%s %d\n",nameA, result[i].second);
}
return 0;
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.