3.19日atc补题 D E
补题情况:
![](https://img-blog.csdnimg.cn/img_convert/dfb0b67f9ac83c30f60e3d8afecebf3c.png)
题解:
D:https://atcoder.jp/contests/abc294/tasks/abc294_d
思路:用c++的set实现,定义俩个set,呼叫一次进入另一个set,被喊走,出set,符合题意时直接输出当前的set的最小元素即可。
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int>a,tmp;
int N,Q;int event;
cin>>N>>Q;
for(int i=1;i<=N;i++)tmp.insert(i);//先让tmp里面为1 2 …n
while(Q--)
{
cin>>event;
if(event==1)
{
a.insert(*tmp.begin());//喊过的进入a
tmp.erase(tmp.begin());//删除最小的,也就是被喊
}
if(event==2)
{
int x;
cin>>x;//x到柜员那
a.erase(x);//a里面的x删除掉
}
if(event==3)
{
cout<<*a.begin()<<endl;//输出a里面最小的
}
}
}
set知识点复习:
set是一个不含有重复元素的容器,且为升序排列
//头文件
#include<set>
//初始化定义
set<int> s;
相关操作:
最小元素的迭代器(理解为指针):s.begin();
最大元素的下个位置的迭代器:s.end();
返回当前set中的元素个数:s.size()
查找这个元素,存在返回迭代器不存在则结束迭代器:s.find(element)
查找这个元素的个数:s.count(element);
插入:s.insert(elment);//插入elmemt进入
删除:s.erase(s.begin())//删除最小元素(注意这里删除的参数为迭代器)
E:https://atcoder.jp/contests/abc294/tasks/abc294_e
思路:利用前缀和,存下当前元素的末尾的位置,用双指针进行一个遍历,若元素相同,则计算出中间相同的部分,指针移动的判定为俩行的元素个数的多少,少的需要加,多的不变,一样的时候都加。
#include<iostream>
#define ull unsigned long long
using namespace std;
const int N=100005;
ull a1[N],b1[N],a2[N],b2[N],sa[N],sb[N];
int main()
{
ull ans=0,sum=0;
ull L;
int N1,N2;
cin>>L>>N1>>N2;
for(int i=1;i<=N1;i++)
{
scanf("%lld%lld",&a1[i],&b1[i]);
sum+=b1[i];
sa[i]=sum;
}sum=0;
for(int i=1;i<=N2;i++)
{
scanf("%lld%lld",&a2[i],&b2[i]);
sum+=b2[i];
sb[i]=sum;
}
for(int i=1,j=1;i<=N1||j<=N2;)
{
if(a1[i]==a2[j])
{
ans+=min(sa[i],sb[j])-max(sa[i-1],sb[j-1]);
}
if(sa[i]==sb[j])
{
i++;
j++;
}else
if(sa[i]>sb[j])
{
j++;
}else
if(sa[i]<sb[j])
{
i++;
}
}
cout<<ans;
}
vj题组刷题:
https://vjudge.net/contest/547627#problem/M
思路:因为存在时间的限制,因此采用bfs找到最短路径,用三维数组去存储,这里要注意输入最高维最好为层数也就是map[2][10][10],扩展的时候要注意扩展点是否为墙,是否为传送点,是否直接为出口(这个可以不用特意去判断,当然判断了时间会快一点,直接判断队首也可以,但时间上稍微要慢一点点)。
#include<iostream>
#include<cstring>
using namespace std;
int next_[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
char a[2][15][15];//地图
struct node
{
int x,y,z;
int step;
}que[500];
int n,m,T;
bool bfs()
{
int head=1,tail=1;
int book[2][15][15]={0};
que[tail].step=0;que[tail].x=0;que[tail].y=0;que[tail].z=0;
tail++;
book[0][0][0]=1;//起点设置为来过
while(head<tail)
{
int x,y,z,s;
x=que[head].x;y=que[head].y;z=que[head].z;s=que[head].step;
if(a[z][x][y]=='P')
{
if(s<=T)//不超过规定时间
{
return true;
}else //超过规定时间
{
return false;
}
}
for(int i=0;i<4;i++)
{
int tx=x+next_[i][0];
int ty=y+next_[i][1];
int tz=z;
if(tx>=0&&ty>=0&&tx<n&&ty<m&&book[tz][tx][ty]==0&&a[tz][tx][ty]!='*')
{
book[tz][tx][ty]=1;//标记为来过
if(a[tz][tx][ty]=='#')//传送器的情况
{
if(tz==0&&a[1][tx][ty]!='*'&&a[1][tx][ty]!='#'&&book[1][tx][ty]==0)//第一层的传送点的情况,第二层落脚点不是传送点不是墙,且没有来过
{
que[tail].x=tx;//入队
que[tail].y=ty;
que[tail].z=1;//改变层数
que[tail].step=s+1;//步数+1
book[1][tx][ty]=1;
tail++;//队尾扩展
}else if(tz==1&&a[0][tx][ty]!='*'&&a[0][tx][ty]!='#'&&book[0][tx][ty]==0)//第二层的传送点,第一层落脚点不是传送点不是墙,且没有来过
{
que[tail].x=tx;//入队
que[tail].y=ty;
que[tail].z=0;//改变层数
que[tail].step=s+1;//步数+1
book[0][tx][ty]=1;
tail++;//队尾扩展
}
}else //不是传送器的情况
{
que[tail].x=tx;//入队
que[tail].y=ty;
que[tail].z=tz;//层数不变
que[tail].step=s+1;
tail++;
}
}
}head++;
}
return false;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m>>T;
getchar();
for(int k=0;k<2;k++)
{
for(int i=0;i<n;i++)
{
cin>>a[k][i];
}
}
if(bfs()==true)
{
cout<<"YES"<<endl;
}
else cout<<"NO"<<endl;
}
}
https://vjudge.net/contest/547627#problem/E
思路:最小操作,bfs出马,利用二维book数组存储俩杯子中不同水量的组合是否出现过,利用数组存储操作,当成功的时候,遍历数组,返回对应操作。
#include<iostream>
#include<queue>
using namespace std;
struct node
{
int wa,wb;
int step;
int s[10010];
};
int book[105][105];
queue<node>que;
int main()
{
int A,B,C;
cin>>A>>B>>C;
node head;
head.wa=0;
head.wb=0;
head.step=0;
book[head.wa][head.wb]=1;
que.push(head);
while(que.empty()!=true)//队列不为空
{
head=que.front();//读取队首
que.pop();//出队
if(head.wa==C||head.wb==C)
{
cout<<head.step<<endl;//输出步数
for(int i=1;i<=head.step;i++)//遍历数组,读取对应操作
{
if(head.s[i]==1)cout<<"FILL(1)"<<endl;
if(head.s[i]==2)cout<<"FILL(2)"<<endl;
if(head.s[i]==3)cout<<"DROP(1)"<<endl;
if(head.s[i]==4)cout<<"DROP(2)"<<endl;
if(head.s[i]==5)cout<<"POUR(1,2)"<<endl;
if(head.s[i]==6)cout<<"POUR(2,1)"<<endl;
}return 0;
}
node tmp;
for(int i=1;i<=6;i++)//6个操作
{
tmp=head;
if(i==1)tmp.wa=A;
if(i==2)tmp.wb=B;
if(i==3)tmp.wa=0;
if(i==4)tmp.wb=0;
if(i==5)//A->B
{
if(head.wa+head.wb<=B)//装的下
{
tmp.wb=head.wa+head.wb;
tmp.wa=0;
}else //装不下
{
tmp.wb=B;
tmp.wa=head.wa-(B-head.wb);
}
}
if(i==6)//B->A
{
if(head.wa+head.wb<=A)//装的下
{
tmp.wb=0;
tmp.wa=head.wa+head.wb;
}else //装不下
{
tmp.wb=head.wb-(A-head.wa);
tmp.wa=A;
}
}
if(book[tmp.wa][tmp.wb]==0)//此种情况的组合没有发生过
{
book[tmp.wa][tmp.wb]=1;
tmp.step=head.step+1;
tmp.s[tmp.step]=i;
que.push(tmp);
}
}
}
cout<<"impossible"<<endl;
return 0;
}
JAVA学习情况:
今天学习了面向对象中的封装,笔记详情:
![](https://img-blog.csdnimg.cn/img_convert/cdba49bb0edaf46ce2cc1ebcb400f0b7.png)
![](https://img-blog.csdnimg.cn/img_convert/65151e2ed78dab731925a529249e36a7.png)
还有private修饰符的作用:防止其他类调用的时候赋值不符合成员变量的规则
![](https://img-blog.csdnimg.cn/img_convert/9fd03f97285be2c024b3a35bd98b7cef.png)
总结:刷题的代码尽量从c往c++改变,熟悉c++,JAVA学习进度加快一点,完成cf的补题。