cf我要变绿

B. Getting Zero

Educational Codeforces Round 126 (Rated for Div. 2) B. Getting Zero

#include<bits/stdc++.h>

using namespace std;
const int N=4e5+10,M=32768;
int dis[N];

void dfs(int k)
{
    //if(dis[k]==15) return;
    if(k<1) return;
    int t;
    if(k%2==0) 
    {
        t=k/2;
        //t=k/2,dis[t]=min(dis[t],dis[k]+1),dfs(t);
        if(dis[t]>dis[k]+1) dis[t]=dis[k]+1,dfs(t);
        if(k!=M) 
        {
            t=k+M,t=t/2;//dis[t]=min(dis[t],dis[k]+1),dfs(t);
            if(dis[t]>dis[k]+1) dis[t]=dis[k]+1,dfs(t);
        }
    }
    if(dis[k-1]>dis[k]+1) dis[k-1]=dis[k]+1,dfs(k-1);
    //t=k-1,dis[t]=min(dis[t],dis[k]+1),dfs(t);
}

void bfs(int k)
{
    queue<int> q;
    q.push(M);
    while(q.size())
    {
        int k;
        int t=q.front();q.pop();
        set<int> res;
        if(t%2==0) res.insert(t/2),res.insert((t+M)/2);
        if(t-1>0) res.insert(t-1);
        
        for(auto x:res)
        {
            if(dis[x]>dis[t]+1)
            {
                dis[x]=dis[t]+1;
                q.push(x);
            }
            
            //dis[x]=min(dis[t]+1,dis[x]);
            //q.push(x);
        }
    }
}

int main()
{
    for(int i=1;i<=M;i++) dis[i]=M;
    dis[M]=0;
    dfs(M);
    //bfs(M);
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int kk;
        scanf("%d",&kk);
        printf("%d ",dis[kk]);
    }
}

这题dfs超时 没有找到解决方法
在bfs中,只有当dis[x]>dis[t]+1时才可以插入到队列中来更新其他答案 ,这样可以节省时间,提高效率,要不然会超时

2

题目链接
在这里插入图片描述题意: 一组数列操作每个减2相邻减1 求得到两个0所需要的最少操作步数。
思路: 分类讨论2个0的位置

1.当2个0间隔大于1时 不会相互影响
2.当2个0间隔为1时会相互影响
3.当两个0相邻时相互影响 每步相当于总数减3 所以答案为(sum+2)/3
在这里插入图片描述

#include<bits/stdc++.h>

using namespace std;
const int N=2e5+10;
int a[N],b[N];
int n;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+1+n);
    int min1=(b[1]+1)/2+(b[2]+1)/2; /这里加一再除2 可以代替 b[1]/2+b[1]%2
    //printf("min1=%d\n",min1);
    for(int i=1;i<=n-1;i++)
    {
        
        if(i==n-1)
        {
            if(max(a[i],a[i+1])/2<min(a[i],a[i+1])) min1=min(min1,(a[i]+a[i+1]+2)/3);
            else min1=min(min1,(max(a[i],a[i+1])+1)/2);
            //if(a[i]%2==1&&a[i+2]%2==1) min1=min(min1,a[i]/2+a[i+2]/2+1);
            //else min1=min(min1,(a[i]+1)/2+(a[i+2]+1)/2);
        }
        else 
        {
            if(a[i]%2==1&&a[i+2]%2==1) min1=min(min1,a[i]/2+a[i+2]/2+1);//相隔一个
            else min1=min(min1,(a[i]+1)/2+(a[i+2]+1)/2);
            
            if(max(a[i],a[i+1])/2<min(a[i],a[i+1]))  min1=min(min1,(a[i]+a[i+1]+2)/3);//两个相邻
            else min1=min(min1,(max(a[i],a[i+1])+1)/2);
        }
        //printf("min1=%d\n",min1);
    }
    printf("%d\n",min1);
}

3
题目链接
在这里插入图片描述题意: 目标为从左下角移到右上角,每次障碍物会往下降落一个单位,判断目标能否完成
注意: 移动可以有8个选择,不止四个
思路: dfs

#include<bits/stdc++.h>

using namespace std;
char a[10][10];

void dfs(int x,int y,int k)
{
    if(k>=7) /这里要多加一个这个  不加会有错误!!!!
    {
        puts("WIN");
        exit(0);
    }
    for(int i=-1;i<=1;i++) /注意这8个方向的枚举方法
        for(int j=-1;j<=1;j++)
        {
            int xx=x+i,yy=y+j;
            if(xx<1||xx>8||yy<1||yy>8) continue;
            if(xx-k>=1&&a[xx-k][yy]=='S') continue;
            if(xx-k-1>=1&&a[xx-k-1][yy]=='S') continue;
            dfs(xx,yy,k+1);
        }
}

int main()
{
    for(int i=1;i<=8;i++) scanf("%s",a[i]+1);
    dfs(8,1,0);
    puts("LOSE");
}

我的做法是: 哈哈 爆内存了 这样需要的空间太大了

#include<bits/stdc++.h>

using namespace std;
char a[10][10];
int dx[5]={0,1,0,-1},dy[5]={1,0,-1,0};
int st[1000];
vector <int> res;
const int N=2e6;
//int res[N],be=1,pos=1,sum=1;
int be=1,pos=1,sum=1;

void move(int x,int y)
{
    if(a[x][y]=='S') return;
    //res(x*8+y);
    be++,sum++;
    res.push_back(x*8+y);
    //res[++pos]=x*8+y;
}

int main()
{
    for(int i=1;i<=8;i++) scanf("%s",a[i]+1);
    
    
    
    //be=1,pos=1,sum=1;
    int stt=1;
    res.push_back(65);
    for(int cnt=1;cnt<=7;cnt++)
    {
        int ress=0;
        memset(st,0,sizeof st);
        for(int i=8;i>=2;i--)
            for(int j=1;j<=8;j++)
            {
                if(a[i-1][j]=='S') 
                {
                    a[i-1][j]='.',a[i][j]='S';
                    st[i*8+j]=1;
                    //st[i*8+j]=1;
                }
            }
            
        int k=res.size();
        for(int i=0;i<k;i++)
        {
            sum--;
            if(sum<0) break;//<=0  当sum=1的时候减1为0
            int xx=res[i]/8,yy=res[i]%8;
            if(yy==0) yy=8;
            if(st[xx*8+yy]==1)
            {
                if(yy-1>=1) move(xx,yy-1);
                if(yy+1<=8) move(xx,yy+1);
            }
            else 
                for(int j=0;j<4;i++)/  其实没有爆内存  是这里写错了
                {
                    int x=xx+dx[j],y=yy+dy[j];
                    if(x>=1&&x<=8&&y>=1&&y<=8) move(x,y);
                }
        }
        printf("res.size()=%d\n",res.size());
        while((k--)&&res.size()) res.erase(res.begin());
        if(sum<=0)
        {
            stt=0;
            break;
        }
    }
    if(stt) puts("WIN");
    else puts("LOSE");
}

我的方法应该是把所有方案都列举了出来,而上面的代码是遍历遇到一个成功就返回,所以我的会超时,浪费了很多时间。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值