P1132 数字生成游戏
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1132 数字生成游戏相关的知识,希望对你有一定的参考价值。
题目请见:传送门
以下为题解,直接从洛谷上搬过来的,还专门改了markdown,(汗)
宽搜 with 一些技巧
- 由于查询量很大,所以要预先处理所有答案
- 预处理当然是用
BFS
,并同时进行delete
,swap
,add
操作。注意,不能在x为队首元素时才更新答案,这样会使效率大打折扣(不更新的话,dist[x]
任为-1,相当于少了判重) - 对于以上三种操作也有要求,一下进行一些优化(炒鸡模拟应该也能过,因为
swap()
,嗯嗯): - 法一:见一楼的题解,不过有局限性
- 法二:针对
add()
,和delete()
,可以然枚举的状态有序化以达到优化效果,适用范围更广泛; - 以下为我的代码,其中结构体部分可以省去,
u.step
可以直接用dist[x]
代替。
#include<queue>
#include<cstdio>
#include<cstring>
main() {}
int dist[10000000];
struct in{int x,s;}u;
std::queue<in>que;
void tie(int *a,int <h,int x) {
lth=0;//解码
while(x) a[lth++]=x%10,x/=10;
}
int dis(int *a,int lth) {
int x=0;//还原
while(lth) x*=10,x+=a[--lth];
return x;
}
void add(int *a,int lth,int step) {
int tmp;//o(n)的add操作
a[lth]=a[lth-1];
for(int i=lth-1;i>=1;i--) {
for(int j=a[i+1]+1;j<a[i-1];j++) {
a[i]=j;
tmp=dis(a,lth+1);
if(dist[tmp]==-1) dist[tmp]=step,que.push((in){tmp,step});
}
a[i]=a[i-1];
}
}
void del(int *a,int lth,int step) {
int tmp,out=0;//o(n)的delete操作
for(int i=lth-1;i>=0;i--) {
out^=a[i]^=out^=a[i];
tmp=dis(a,lth-1);
if(dist[tmp]==-1) dist[tmp]=step,que.push((in){tmp,step});
}
}
void swa(int *a,int lth,int step) {
int tmp;//o(n*(n-1)/2)的swap操作
for(int i=0;i<lth;i++) {
for(int j=i+1;j<lth;j++) {
if(a[i]==a[j]) continue;
a[i]^=a[j]^=a[i]^=a[j];
tmp=dis(a,lth);
if(dist[tmp]==-1) dist[tmp]=step,que.push((in){tmp,step});
a[i]^=a[j]^=a[i]^=a[j];
}
}
}
int entry() {
memset(dist,-1,sizeof dist);
int a[10],lth,lmt,x;
scanf("%d",&x);
tie(a,lmt,x),dist[x]=0;
que.push((in){x,0});
while(!que.empty()) {
u=que.front();
que.pop();
memset(a,0,sizeof a);
tie(a,lth,u.x);
if(lth>1) del(a,lth,u.s+1),tie(a,lth,u.x);
if(lth>1) swa(a,lth,u.s+1),tie(a,lth,u.x);
if(lth<lmt) add(a,lth,u.s+1);
}
scanf("%d",&lmt);
while(lmt--) {
scanf("%d",&x);
printf("%d\\n",dist[x]);
}
return 0;
}
int aptal=entry();
以上是关于P1132 数字生成游戏的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段