22/5/27

1,robot instructions;


1,robot instructions

题意:给出n条指令,和终点edx,edy,初始位置在(0,0);每条指令包含xi,yi,执行指令操作是使当前坐标x+=xi, y+=yi,问对于执行1~n次指令,可以到达终点的指令数量分别有多少;n<=40;(特别说明:时间限制和内存限制翻倍,分别是4s和512mb);

思路:肯定是要枚举每个点的状态,选还是不选,这样的时间复杂度是O(2^n),n最大是40,这个复杂度肯定要t掉的,所以考虑优化;

对于枚举点的状态,双向dfs可以很好的做到降低2^(n/2)的复杂度;并且2^21在1e7的范围,对于4s的限制来说也不算严格;

第一代版本:

#pragma GCC optimize(2)

#include<bits/stdc++.h>

#define rep1(i,a,n) for( int i=a;i<n;++i)

#define rep2(i,a,n) for( int i=a;i<=n;++i)

#define per1(i,n,a) for( int i=n;i>a;i--)

#define per2(i,n,a) for( int i=n;i>=a;i--)

#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)

#define memset(a,i,b) memset((a),(i),sizeof (b))

#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))

#define pro_q priority_queue

#define pb push_back

#define pf push_front

#define endl "\n"

#define lowbit(m) ((-m)&(m))

#define YES cout<<"YES\n"

#define NO cout<<"NO\n"

#define Yes cout<<"Yes\n"

#define No cout<<"No\n"

#define yes cout<<"yes\n"

#define no cout<<"no\n"

#define yi first

#define er second

using namespace std;

typedef pair<int,int> PII;

typedef pair<long long,long long>PLL;

typedef pair<int,PII> PIII;

typedef long long ll;

typedef double dob;

const int N=110;

struct node

{

    ll x,y;

}zb[N];

map<PLL,vector<ll>>map_cs;

ll ans[N];

int n,edx,edy,k;

void dfs(int u,ll cs,ll x,ll y)

{

    if(u>k)return;

    if(u==k)

    {

        ll cx=edx-x,cy=edy-y;

        ll siz=map_cs[{cx,cy}].size();

       // cout<<siz<<endl;

        if(siz)

        {

            rep1(i,0,siz)

            {

                ans[cs+map_cs[{cx,cy}][i]]++;

                //cout<<cs+map_cs[{cx,cy}][i]<<endl;

            }

        }

        return;

    }

    dfs(u+1,cs+1,x+zb[u].x,y+zb[u].y);

    dfs(u+1,cs,x,y);

}

void dfs2(int u,ll cs,ll x,ll y)

{

    if(u>n)return;

    if(u==n)

    {

        map_cs[{x,y}].pb(cs);

        return;

    }

    dfs2(u+1,cs+1,x+zb[u].x,y+zb[u].y);

    dfs2(u+1,cs,x,y);

}

signed main()

{

    quick_cin();

    cin>>n>>edx>>edy;

    k=n/2;

    rep1(i,0,n)

        cin>>zb[i].x>>zb[i].y;

    dfs2(k,0,0,0);

    dfs(0,0,0,0);

    rep2(i,1,n)cout<<ans[i]<<endl;

    return 0;

}

但是很不幸, ;我觉得是map带的log可能给卡了,于是又写了

Unordered_map版,把两个数哈希映射下;

第二版:

const int N=110;

struct node

{

    ll x,y;

}zb[N];

ll get(ll x,ll y)

{

    return x*1000000000ll+y;

}

unordered_map<ll,vector<ll>>map_cs;

ll ans[N];

int n,edx,edy,k;

void dfs(int u,ll cs,ll x,ll y)

{

    if(u>k)return;

    if(u==k)

    {

        ll cx=edx-x,cy=edy-y;

        ll jl=get(cx,cy);

        ll siz=map_cs[jl].size();

       // cout<<siz<<endl;

        if(siz)

        {

            rep1(i,0,siz)

            {

                ans[cs+map_cs[jl][i]]++;

                //cout<<cs+map_cs[{cx,cy}][i]<<endl;

            }

        }

        return;

    }

    dfs(u+1,cs+1,x+zb[u].x,y+zb[u].y);

    dfs(u+1,cs,x,y);

}

void dfs2(int u,ll cs,ll x,ll y)

{

    if(u>n)return;

    if(u==n)

    {

        map_cs[get(x,y)].pb(cs);

        return;

    }

    dfs2(u+1,cs+1,x+zb[u].x,y+zb[u].y);

    dfs2(u+1,cs,x,y);

}

signed main()

{

    quick_cin();

    cin>>n>>edx>>edy;

    k=n/2;

    rep1(i,0,n)

        cin>>zb[i].x>>zb[i].y;

    dfs2(k,0,0,0);

    dfs(0,0,0,0);

    rep2(i,1,n)cout<<ans[i]<<endl;

    return 0;

}

但是还是tle了;肯定是其他的地方常数太大了;

看着代码,猛然发觉 是个很玄学的因素,试着输出了一下,竟然1e4的大小都有,所以肯定不能留着这个循环;

对于每个后半段存的偏移量所需要的次数,有着重复的地方;(比如在4,5和在6,7)都是拿了两次,需要的次数都是2,所以可以将重复的统计起来,按次数分类;所以把vector改成unordered_map即可;然后每次统计0~n中有cs的即可;

第三版:

const int N=110;

struct node

{

    ll x,y;

}zb[N];

ll get(ll x,ll y)

{

    return x*1000000000ll+y;

}

unordered_map<ll,unordered_map<int,int>>map_cs;

ll ans[N];

int n,edx,edy,k;

void dfs(int u,ll cs,ll x,ll y)

{

    if(u>k)return;

    if(u==k)

    {

        ll cx=edx-x,cy=edy-y;

        ll jl=get(cx,cy);

        rep2(i,1,n-cs)

        {

            ans[cs+i]+=map_cs[jl][i];

        }

        return;

    }

    dfs(u+1,cs+1,x+zb[u].x,y+zb[u].y);

    dfs(u+1,cs,x,y);

}

void dfs2(int u,ll cs,ll x,ll y)

{

    if(u>n)return;

    if(u==n)

    {

        map_cs[get(x,y)][cs]++;

        return;

    }

    dfs2(u+1,cs+1,x+zb[u].x,y+zb[u].y);

    dfs2(u+1,cs,x,y);

}

signed main()

{

    quick_cin();

    cin>>n>>edx>>edy;

    k=n/2;

    rep1(i,0,n)

        cin>>zb[i].x>>zb[i].y;

    dfs2(k,0,0,0);

    dfs(0,0,0,0);

    rep2(i,1,n)cout<<ans[i]<<endl;

    return 0;

}

但是竟然mle了, ,思来想去,之前用vector存的带重复的元素都没mle,没重复的元素竟然mle了,不能理解;

那么unordered_map为何会mle呢,初始化肯定都是0,但是没有存数据;可能在某个点全给它存了数据,导致mle;于是在

,加了个if判断,ac了;

总结:dfs暴搜的时间复杂度分析确实玄学(y总亲言),但是应该尽量降低常数因子;

map虽然默认数据是0,但是还是判断下比较好,不然会自动填充该数据,对于暴搜dfs来说,也很容易mle(虽然给了512mb);

ac code:时间复杂度O( n*2^(n/2) )

#pragma GCC optimize(2)

#include<bits/stdc++.h>

#define rep1(i,a,n) for( int i=a;i<n;++i)

#define rep2(i,a,n) for( int i=a;i<=n;++i)

#define per1(i,n,a) for( int i=n;i>a;i--)

#define per2(i,n,a) for( int i=n;i>=a;i--)

#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)

#define memset(a,i,b) memset((a),(i),sizeof (b))

#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))

#define pro_q priority_queue

#define pb push_back

#define pf push_front

#define endl "\n"

#define lowbit(m) ((-m)&(m))

#define YES cout<<"YES\n"

#define NO cout<<"NO\n"

#define Yes cout<<"Yes\n"

#define No cout<<"No\n"

#define yes cout<<"yes\n"

#define no cout<<"no\n"

#define yi first

#define er second

using namespace std;

typedef pair<int,int> PII;

typedef pair<long long,long long>PLL;

typedef pair<int,PII> PIII;

typedef long long ll;

typedef double dob;

const int N=50;

struct node

{

    ll x,y;

}zb[N];

ll get(ll x,ll y)

{

    return x*1000000000ll+y;

}

unordered_map<ll,unordered_map<int,ll>>map_cs;

ll ans[N];

int n,edx,edy,k;

void dfs(int u,ll cs,ll x,ll y)

{

    if(u>k)return;

    if(u==k)

    {

        ll cx=edx-x,cy=edy-y;

        const ll jl=get(cx,cy);

        rep2(i,0,n-cs)

        {

            if(map_cs[jl].count(i))ans[cs+i]+=map_cs[jl][i];

        }

        return;

    }

    dfs(u+1,cs+1,x+zb[u].x,y+zb[u].y);

    dfs(u+1,cs,x,y);

}

void dfs2(int u,ll cs,ll x,ll y)

{

    if(u>n)return;

    if(u==n)

    {

        map_cs[get(x,y)][cs]++;

        return;

    }

    dfs2(u+1,cs+1,x+zb[u].x,y+zb[u].y);

    dfs2(u+1,cs,x,y);

}

signed main()

{

    quick_cin();

    cin>>n>>edx>>edy;

    k=n/2;

    rep1(i,0,n)

        cin>>zb[i].x>>zb[i].y;

    dfs2(k,0,0,0);

    dfs(0,0,0,0);

    rep2(i,1,n)cout<<ans[i]<<endl;

    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Dull丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值