目录
1. 不要浪费金币
输入样例:
10 10
1 2 3 4 1 2 3 5 11 1
输出样例:
4
具体实现代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(void){
ll n,m;
ll ans=0; //最终次数
ll sums=0;
cin>>n>>m;
for(int i=0;i<n;i++){
int t;
cin>>t;
if(sums+t>m){
ans++;
sums=t;
}else{
sums+=t;
}
}
cout<<ans;
return 0;
}
2. 智能服药助手
输入样例:
10 6
1 2 3 4 5 -1 -1 -1 -1 -1
0 1 1
1 2 1 2
2 1 2
3 2 1 3
5 3 1 3 4
6 2 1 4
输出样例:
Don't take 2 at 2!
Don't take 3 at 5!
Don't take 4 at 6!
具体代码实现:
//思路:计算每个药品的间隔时间,如果小于规定时间就错误
//1. 怎么计算间隔时间-->a[药品]=时间,默认为-1(表示还未服用)
//如果没有时间要求就不参与计算
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1010;
ll st[N]; //记录每个药品的间隔时间
ll a[N]; //药品的吃药时间
int main(void){
ll n,m;
memset(a,-1,sizeof(a)); //-1表示还未服用
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>st[i];
}
for(int i=0;i<m;i++){ //吃药记录
ll t,k;
cin>>t>>k;
for(int j=0;j<k;j++){
int r; //吃的药品
cin>>r;
if(st[r]!=-1){ //药品如果有时间要求
if(a[r]!=-1){ //之前服用过该药品
ll cha=t-a[r]; //计算时间间隔
if(cha<st[r]){
cout<<"Don't take "<<r<<" at "<<t<<"!"<<endl;
}else{
a[r]=t;
}
}else{
a[r]=t;
}
}
}
}
return 0;
}
3. 跑团机器人
输入样例:
d6+3d5+2-2d3+2d5
输出样例:
3 2
5 5
6 1
2 31
具体代码实现:
需要考虑到输入字符串开头带+/-符号,例如”+3d4+5“,"-3d4+5"
//思路:
//1. 需要将string类型的每一项分开
//2. map<ll,ll>存储面数+个数(map自动带有从小到大排序)
//3. 最大值最小值一并计算
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>mp; //面数+个数
ll mmax=0,mmin=0; //最大值、最小值
int main(void){
string s;
cin>>s;
//1.将字符串的每一项进行拆分
int a=0,b=0; //双指针
while(b<s.size()){
if(b!=0&&(s[b]=='+'||s[b]=='-'||b+1==s.size())){
if(b+1==s.size())
b++;
string s1=s.substr(a,b-a); //找到每一项
a=b;
//2. 每一项进行拆分
int t=s1.find('d'); //找到每一项中间d
if(t!=string::npos){ //找到了
string s2=s1.substr(t+1); //面数
string s3=s1.substr(0,t); //个数
ll n,m; //个数、面数
m=stoi(s2);
if(s3.empty()){ //开头省略1
n=1;
}else if(s3.size()==1){ //中间省略1
if(s3[0]=='+')
n=1;
else
n=-1;
}else{
n=stoi(s3);
}
mp[m]+=abs(n);
if(n>0){
mmax+=n*m;
mmin+=n*1;
}else{
mmax+=n*1;
mmin+=n*m;
}
}else{ //表示是一个值
mmax+=stoi(s1);
mmin+=stoi(s1);
}
}
b++;
}
for(auto it:mp){
cout<<it.first<<" "<<it.second<<endl;
}
cout<<mmin<<" "<<mmax;
return 0;
}
tips:
1. s.find(a)函数可以寻找a(字符/字符串)在字符串s的位置,能找到则返回第一次出现的位置(字符串a的话返回的即是字符串的首地址),找不到则返回string::npos.
4. 攻略分队
输入样例1:
6 8 7 5 3 0
010
101
110
001
111
000
输出样例1:
2 3
1 4 5
输入样例2:
6 8 7 5 3 0
010
101
010
001
011
000
输出样例2:
GG
具体代码实现:
//思路:
//1.怎么将随机分组所有的情况弄出来
//->左移和右移+与运算
//2. 怎么判断不唯一
//->另取一个值为okk
//3. 怎么实现规则的先后
//->优先级
#include<bits/stdc++.h>
using namespace std;
int v[7];
vector<int> q; //存储存在的组号,便于后续分组
int r[7][3]; //存储每一个角色(行标从1开始)
vector<int> a,b; //存储最优的分组情况
int ok=-1,okk=-1; //优先级,判断是否唯一
int cha=10000,vis=0; //分组两边人数之差
int check(vector<int> &x,vector<int>&y){
int q1[3],q2[3]; //用于统计每支队伍的特殊角色
int num1=0,num2=0; //每支队伍的人数
okk=-1; //需要重置,判断是否答案不唯一
memset(q1,0,sizeof(q1));
memset(q2,0,sizeof(q2));
for(int u:x){ //u表示组号
num1+=v[u];
for(int i=0;i<3;i++){
q1[i]+=r[u][i];
}
}
for(int u:y){
num2+=v[u];
for(int i=0;i<3;i++)
q2[i]+=r[u][i];
}
//0.必须满足基础条件(至少有一个MT)
if(!q1[0]||!q2[0]) return 0;
//1.规则1->优先级为2
if(q1[1]&&q1[2]&&q2[1]&&q2[2]){
if(ok<2){
ok=2;
cha=abs(num1-num2);
vis=num1>=num2?1:0;
return 1;
}
okk=2; //第二次满足规则1时,okk=ok;
}else if(q1[2]&&q2[2]){ //规则2->优先级为1
if(ok<1){
ok=1;
cha=abs(num1-num2);
vis=num1>=num2?1:0;
return 1;
}
okk=1;
}else if(q1[0]&&q2[0]){ //规则0->优先级为0
if(ok<0){
ok=0;
cha=abs(num1-num2);
vis=num1>=num2?1:0;
return 1;
}
okk=0;
}
//规则012不唯一的时候
if(ok==okk){
int ncha=abs(num1-num2);
if(ncha<cha){ //规则3
cha=ncha;
vis=num1>=num2?1:0;
return 1;
}
if(ncha==cha){ //规则3不唯一
int nvis=num1>=num2?1:0;
if(nvis>vis){ //规则4
vis=nvis;
return 1;
}
if(nvis==vis){
return x<a;
}
}
}
return 0;
}
int main(void){
string s;
for(int i=1;i<=6;i++){
cin>>v[i];
if(v[i]>0)
q.push_back(i);
}
for(int i=1;i<=6;i++){
cin>>s;
for(int j=0;j<3;j++){
r[i][j]=s[j]-'0';
}
}
//1. 随机分组,列出所有可能的情况
int n=q.size();
vector<int> x,y; //存储分组的组号。
for(int i=1;i<(1<<n);i++){
x.clear();
y.clear();
for(int j=0;j<n;j++){ //j用来得到每一位的数值
if((i>>j)&1){ //&运算只看最后一位
x.push_back(q[j]);
}else{
y.push_back(q[j]);
}
}
if(check(x,y)){
a=x;
b=y;
}
}
//得到最终结果
if(!a.size()||!b.size()){
cout<<"GG";
return 0;
}
for(int i=0;i<a.size();i++){
if(i!=0) cout<<" ";
cout<<a[i];
}
cout<<endl;
for(int i=0;i<b.size();i++){
if(i!=0) cout<<" ";
cout<<b[i];
}
return 0;
}
5. 树与二分图
输入样例:
7
1 2
2 3
2 4
2 5
2 6
4 7
输出样例:
4
具体代码实现:
//思路:
//1. 大概思路
//二分图:也就是相邻边上的点不能在同一集合中
//树也就是一个二分图->奇数层的点在一集合,偶数层在一集合
//假设偶数层even个,奇数层odd个,那么最多可以连接n*m条线
//odd*even-(n-1)->结果
//2. 存储
//n最大可以为10的6次方,故使用vector<int> f[N]
//3. 怎么确认树的奇数层和偶数层?
//遍历每一个点,如果不是父节点,与该点相邻的则是下一层的点
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
int n;
ll odd,even;
vector<int> f[N];
void dfs(int num,int pre,int c){
if(c%2==0)
even++;
else odd++;
for(auto x:f[num]){ //f[num]表示与点num相连的点
if(x!=pre)
dfs(x,num,c+1);
}
}
int main(void){
cin>>n;
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
f[a].push_back(b);
f[b].push_back(a);
}
dfs(1,-1,1); //点的序号,父节点,第几层
cout<<odd*even-(n-1);
return 0;
}
最后,附上题目链接:PTA | 程序设计类实验辅助教学平台 (pintia.cn)