1545: 完美变换
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 35 Solved: 13
[ Submit][ Status][ Web Board]
Description
给你一个数n,每次只能进行减1 或者加2的操作,如果n能整除3,可以进行除3的操作,能用最少的次数把n进行以上操作后变为1的操作称为n的一个最小变换,比如7->9->3->1,7->6->2->1 都是n的最小变换,最小变换次数为3,在最小变换中,字典序最小的序列称为完美变换序列。求n的最小变换次数和完美变换序列
Input
输入多组数据,每行输入一个整数n (2<=n<=10^9)
Output
对于每个n,输出最小变换次数,输出一个空格,再输出完美变换序列,序列中每两个数之间用 -> 连接。
Sample Input
7
Sample Output
3 7->6->2->1
【分析】
乍一看以为是个什么高端数论.....n有点大,但是想一想可以发现其实可以搜啊....对当前now有三个操作/3,-1,+2,但是dfs显然会超时,所以改成bfs...结果就过了....
就是输出稍微有一点麻烦,不过也还好...bfs过程中用一个father数组记录路径,然后递归倒过来输出就可以了。
因为这里的n比较大所以vis标记需要用map,数组开不下的...另外这里我一开始以为不需要清空vis和father,因为我下意识的以为可以重复利用...MLE一次之后就发现自己太蠢了...大概半夜做题目脑子蠢蠢的hhh
【代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
map<int,int>father;
map<int,bool>vis;
void write(int x)
{
if (father[x]==x)
printf("%d",x);
else
{
write(father[x]);
printf("->%d",x);
}
}
void bfs(int n)
{
vis.clear();
father.clear();
queue<pair<int,int> >q;
q.push(make_pair(n,0));
vis[n]=1;
father[n]=n;
int now,noww;
while (!q.empty())
{
now=q.front().first;
noww=q.front().second;
if (now==1)
{
printf("%d ",noww);
write(1);
puts("");
return ;
}
q.pop();
if (now%3==0&&!vis[now/3])
{
q.push(make_pair(now/3,noww+1));
father[now/3]=now;
vis[now/3]=1;
}
if (!vis[now-1])
{
q.push(make_pair(now-1,noww+1));
father[now-1]=now;
vis[now-1]=1;
}
if (!vis[now+2])
{
q.push(make_pair(now+2,noww+1));
father[now+2]=now;
vis[now+2]=1;
}
}
}
int main()
{
int n;
while (~scanf("%d",&n)) bfs(n);
return 0;
}