3.20~3.21总结

3.19日atc补题 D E

补题情况:

题解:

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学习情况:

今天学习了面向对象中的封装,笔记详情:

还有private修饰符的作用:防止其他类调用的时候赋值不符合成员变量的规则

总结:刷题的代码尽量从c往c++改变,熟悉c++,JAVA学习进度加快一点,完成cf的补题。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡卡卡卡罗特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值