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;
}