赞
踩
题目
你被委托开发一个用于睿抗机器人开发者大赛CAIP-编程技能赛的管理系统,这个管理系统需要一些账号名和密码,你需要按照规则根据账号生成对应的密码,具体规则是:
现在给定账号名以及轮次,请你生成对应的密码。
思路
按照题意操作,改变字母大小写时,可以先把所有替换字母存入map中,找连续字母的时候用while循环。如果S为yourname,随便改一个字符串
代码
#include<bits/stdc++.h> using namespace std; unordered_map<char,char>mp; int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int n; string e; cin>>n>>e; if(e=="yourname")e="zhenhao"; for(int i=0;i<25;i++)mp['A'+i]='B'+i,mp['b'+i]='a'+i; mp['Z']='A'; mp['a']='z'; string s=e; int m=s.size(); while(n--){ for(int i=0;i<m;i++){ if((s[i]>='a'&&s[i]<='z')||(s[i]>='A'&&s[i]<='Z')) s[i]=mp[s[i]]; } for(int i=0;i<m;i++){ int j=i; while(s[j]>='a'&&s[j]<='z'){ if(j-i+1==3) for(int k=i;k<=j;k++)s[k]=toupper(s[k]); else if(j-i+1>3)s[j]=toupper(s[j]); j++; } if(j-i>=3){ i=j-1; continue; } j=i; while(s[j]>='A'&&s[j]<='Z'){ if(j-i+1==3) for(int k=i;k<=j;k++)s[k]=tolower(s[k]); else if(j-i+1>3)s[j]=tolower(s[j]); j++; } if(j-i>=3)i=j-1; } } cout<<e<<'\n'<<s; return 0; }
题目
小 C 和他的朋友一起玩一个桌游。游戏开始的时候,一共有 6 种不同颜色的卡牌,每种颜色有 8 张卡牌,其中一面写着 1 到 8 的数字,每种颜色的每个数字的卡牌只有一张。每位玩家需要从每种颜色的卡牌中抽取一张,并将卡牌摆放在自己的面前,卡牌上的数字朝外,所有玩家坐成一圈,这样所有玩家能看见其他玩家卡牌上的颜色及数字,也能看见自己的卡牌的颜色,但看不到自己的卡牌的数字。
游戏会进行若干轮,每次轮到某位玩家的时候,玩家可以选择三种不同的颜色,再选择一个范围 [L,R],询问一次其他玩家,自己对应的三种颜色的卡牌的数字之和是不是在范围内。其他玩家可以如实地回答“是”或“不是”。在游戏最后玩家需要猜测出自己卡牌上的数字是什么。
为了提高自己的游戏水平,小 C 决定考虑一个简化的问题:现在游戏刚刚开始,小 C 第一个进行询问。不难发现,进行询问后,小 C 可以根据回答排除一些自己卡牌上的数字的不可能的情况。例如选择红色、黄色、蓝色三种颜色的卡牌,询问三种颜色卡牌上的数字和的范围是否为 [5,8],假设回答是“是”,那么显然不可能出现红色卡牌数字为 2、黄色卡牌数字为3、蓝色卡牌数字为 4 的情况。
进一步地,对于一个询问,假设其他玩家给出的回答为“是”的时候可以排除的自己卡牌数字的可能方案数为 K1,给出的回答为“不是”的时候可以排除的可能方案数为 K2。小 C 自然希望自己的询问能够在不同的情况下尽可能排除更多的情况,因此小 C 希望自己的询问能够最大化 Min(K1,K2) 的值。
请你求出在询问达到以上要求的情况下,小 C 卡牌数字剩余的可能方案数为多少。
思路
因为N最多为7,T最多为5,卡牌范围1到8,所以完全可以枚举所有可能情况。题目要求最大化MIN(K1,K2)的同时,输出最多的可能值,那么就是输出MAX(K1,K2)*pow(8-n,3),其中pow(8-n,3)就是其它三张牌的可能值
代码
#include<bits/stdc++.h> using namespace std; int b[10][10]; pair<int,int>ans; pair<int,int>tmp; void dfs(int x1,int x2,int x3,int cnt,int l,int r,int sum){ if(cnt==4){ if(sum>=l&&sum<=r)ans.first++; else ans.second++; return; } int t=-1; if(cnt==1)t=x1; else if(cnt==2)t=x2; else t=x3; for(int i=1;i<=8;i++){ if(b[t][i])continue; dfs(x1,x2,x3,cnt+1,l,r,sum+i); } } void check(){ if(min(tmp.first,tmp.second)<min(ans.first,ans.second)){ tmp=ans; } else if(min(tmp.first,tmp.second)==min(ans.first,ans.second)){ if(abs(tmp.first-tmp.second)<abs(ans.first-ans.second)) tmp=ans; } } void solve(){ int n; cin>>n; tmp={0,0}; memset(b,0,sizeof b); for(int i=1;i<=n;i++){ for(int j=1;j<=6;j++){ int x; cin>>x; b[j][x]=1; } } for(int i=1;i<=6;i++){ for(int j=i+1;j<=6;j++){ for(int k=j+1;k<=6;k++){ for(int l=3;l<=24;l++){ for(int r=l;r<=24;r++){ ans={0,0}; dfs(i,j,k,1,l,r,0); check(); } } } } } cout<<max(tmp.first,tmp.second)*pow(8-n,3)<<'\n'; } int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t; cin>>t; while(t--){ solve(); } return 0; }
题目
兰州拉面是著名美食,其煮面很有讲究,不同种类的面需要煮不同的时长。拉面馆的煮面师傅的规则很简单,只要手头有煮面篮子是空闲的,就把下一份客单指定的面放到空闲篮子里煮;如果空闲的篮子不止一个,那么先放到其中编号最小的篮子里煮;如果没有篮子是空闲的,就等待。一个篮子里的面煮够了时间,师傅要准时捞出来放到该客单对应的碗里,招呼服务员端给客人;如果有多个篮子里的面同时到了捞取时间,师傅会同时捞起,但要本着先到先得的原则,按下单顺序招呼送餐。
在生意火爆的拉面馆里,煮面师傅需要很强的记忆力和计时能力,才能面对源源不断的客单,同时照顾一大堆煮面篮子而不出错。如果面的品种不太多,篮子也不太多,那一位拉面师傅的大脑还是能应对的。但如果我们有上千种面、上万只煮面篮、数十万客单呢…… 这就需要请你帮忙,写个派餐系统来完成这个任务了。
思路
两个要求,一是如果有多个空篮子,放编号最小的篮子里煮;二是如果有多个篮子同时完成,先给编号小的客人
那就设两个优先队列,一个排序出篮时间和客人编号、一个排序篮子编号
代码
#include<bits/stdc++.h> using namespace std; const int N=1e3+5,M=1e4+5; int a[N]; //记录每种面时间 int b[M]; //记录每个锅用了几次 struct node{ int numb; //顾客编号 int id; //锅编号 int time; //时间 bool operator<(const node&x)const{ if(time==x.time)return numb>x.numb; return time>x.time; } }; priority_queue<node>q; priority_queue<int,vector<int>,greater<int>>p; //存空锅 bool flag; void print(node t){ if(flag)cout<<" "; flag=true; cout<<t.numb<<':'<<t.time; } int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int n,m,l; cin>>n>>m>>l; for(int i=1;i<=n;i++)cin>>a[i]; int tot=0,x; int TIME=0; //记录当前时间 for(int i=1;i<=l;i++){ cin>>x; if(tot<m){ q.push({i,++tot,TIME+a[x]}); b[tot]++; continue; } if(!p.empty()){ //如果有篮子是空的 auto t=p.top(); p.pop(); q.push({i,t,TIME+a[x]}); b[t]++; continue; } if(q.size()>1){ //找同一时间出锅 auto now1=q.top(); q.pop(); auto now2=q.top(); if(now1.time!=now2.time)q.push(now1); else{ q.pop(); TIME=now1.time; print(now1); print(now2); p.push(now1.id); p.push(now2.id); while(!q.empty()){ auto now3=q.top(); if(now3.time!=TIME)break; q.pop(); print(now3); p.push(now3.id); } } } if(!p.empty()){ //如果有篮子是空的 auto t=p.top(); p.pop(); q.push({i,t,TIME+a[x]}); b[t]++; } else{ auto t=q.top(); q.pop(); TIME=t.time; print(t); q.push({i,t.id,TIME+a[x]}); b[t.id]++; } } while(!q.empty()){ auto t=q.top(); q.pop(); print(t); } cout<<'\n'; for(int i=1;i<=m;i++)cout<<b[i]<<("%c",i==m?'\n':' '); return 0; }
题目
给定一个由带编号的积木搭成的长方体。其中每块积木的厚度都一样,由若干个单位边长的相邻方块组成(相邻是指两个方块有一面重合)。现在要求将这个长方体中的积木一块一块拆掉。每块积木只能从顶端取出,并且取出时不能移动还在长方体中的其它积木。请你给出一个拆积木的顺序。当然这种顺序可能是不唯一的,我们规定当有多种选择时,总是取出编号最小的那个。
思路
拓扑排序,将每个上行的编号与下行编号设路径
代码
#include<bits/stdc++.h> using namespace std; const int N=1e3+5,M=1e6+5; int mp[N][N],cnt; int b[M]; //记录被覆盖的数量 bool vis[M]; int to[M],from[M],head[M],idx; void add(int u,int v){ to[idx]=v,from[idx]=head[u],head[u]=idx++; } priority_queue<int,vector<int>,greater<int>>q; int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int n,m; cin>>n>>m; memset(head,-1,sizeof head); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>mp[i][j]; if(!vis[mp[i][j]]){ vis[mp[i][j]]=true; cnt++; //记录编号数量 } if(i!=1&&mp[i][j]!=mp[i-1][j]){ add(mp[i-1][j],mp[i][j]); b[mp[i][j]]++; } } } memset(vis,false,sizeof vis); for(int i=1;i<=m;i++){ if(b[mp[1][i]])continue; if(vis[mp[1][i]])continue; vis[mp[1][i]]=true; q.push(mp[1][i]); } if(q.empty()){ cout<<"Impossible"; return 0; } int tot=0; while(!q.empty()){ auto now=q.top(); q.pop(); if(tot++)cout<<' '; cout<<now; bool flag=true; for(int i=head[now];i!=-1;i=from[i]){ int j=to[i]; if(--b[j]==0){ flag=false; q.push(j); } } if(tot==cnt)break; if(q.empty()&&flag){ cout<<" Impossible\n"; return 0; } } return 0; }
题目
现在有两个大小分别为 C1 和 C2 的栈,以及一个固定长度的数组,数组的每个位置一开始都是空的。只要数组仍然有空间,每次你可以从任意一个栈顶取出一个数字放置在数组的任意空位,然后判断数组里是否有 K 个相同的数字,如果有的话,那么你可以从数组里删除这 K 个数字,删除后的空间可以继续用于放置其他数字。
请问如果要将两个栈全部清空,数组的长度至少是多少?
思路
dp[ i ] [ j ]第一个存栈当前容量,第二个存最大使用过的容量,然后每到一个dp[ i ] [ j ] ,它可能是从C1中取出一个新数字、也可能是从C2中取出一个新数字,所以要判断新数字能不能删除要从两个方面比较。
代码
#include<bits/stdc++.h> using namespace std; const int N=1e3+5,M=2e3+5; int a1[N],a2[N]; int pre1[M],pre2[M]; pair<int,int>dp[N][N]; int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t; cin>>t; while(t--){ int n,m,k; cin>>n>>m>>k; for(int i=1;i<=n;i++)cin>>a1[i]; for(int i=1;i<=m;i++)cin>>a2[i]; memset(dp,0x3f3f3f3f,sizeof dp); memset(pre1,0,sizeof pre1); dp[0][1]=dp[1][0]={1,1}; for(int i=1;i<=n;i++){ for(int j=0;j<M;j++)pre2[j]=0; for(int j=1;j<=m;j++){ int val1=1,val2=1; if((pre1[a1[i]]+pre2[a1[i]]+1+(a1[i]==a2[j]))%k==0)val1-=k; if((pre1[a2[j]]+pre2[a2[j]]+1+(a1[i]==a2[j]))%k==0)val2-=k; int t1=max(dp[i-1][j].second,dp[i-1][j].first+1); int t2=max(dp[i][j-1].second,dp[i][j-1].first+1); if(t1!=t2){ if(t1<t2) dp[i][j]={dp[i-1][j].first+val1,t1}; else dp[i][j]={dp[i][j-1].first+val2,t2}; } else{ int tmp=min(dp[i-1][j].first+val1,dp[i][j-1].first+val2); dp[i][j]={tmp,t1}; } pre2[a2[j]]++; } pre1[a1[i]]++; } cout<<dp[n][m].second<<'\n'; } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。