【t008】钱币变换问题
Time Limit: 2 second
Memory Limit: 32 MB
【问题描述】
给定 2*n 个方格,将其排成一行。选择两个相邻的方格,设置为空方格,初始时不放钱币。而其余的方格共放入 n-1 枚金币和 n-1 枚银币,每个方格恰好放入1枚钱币。
平移操作:相邻的两个非空方格中的钱币可以平行移动到两个相邻的空方格中,但不能改变这两枚钱币的排列顺序。
金币变换问题要求用最少移动次数将所有金币移到所有银币的左边。
编程任务:对于给定的 n-1 枚金币和 n-1 枚银币的初始排列,设计一个分支限界法,计算满足要求的最少移动次数。
【输入格式】
第一行有一个正整数 T ,表示有 T 组测试数据。每组测试数据包括两行,第一行是一个整数 n ,第二行是 n-1 枚金币,n-1 枚银币和两个空方格的初始排列,字母 a 表示金币,字母 b 表示银币,字符‘.’表示空方格。。
输入数据保证初始排列中,两个空方格是相邻的。0 ≤ T ≤ 100,2 ≤ n ≤ 10。
【输出格式】
对于每组测试数据,输出一行一个整数,表示最少需要移动的次数;如果无解,请输出一行“No Solution”。
【输入样例】
3
3
abab..
5
abba..abab
6
a..babbababa
【输出样例】
No Solution
3
4
【样例说明】
初始: abba..abab
第一步:abbabaa..b
第二步:a..abaabbb
第三步:aaaab..bbb
达到目标,所有的a都在b左边。
这就是3步的解法。
【题解】
C++党直接用map来判重就可以了。
我用的是字典树。字典树可以作为另类的"map".就是变成访问一条路径而已。
用链表来建树。因为只有3个字符'a','b','.',所以在结构体中只要开3个位置就好。
然后新的指针。其下一个一定要改为NULL。不然会出错(有时候不是NULL)。
然后输入多个字符的时候,不要用cin,而应该用scanf,然后再转成string类进行操作。
在广搜的队列中,要记录点号的位置,不然每次都要重新找一遍,很费时。
如果用暴力的hash去做。最后一个点会超时。
a全部在b左边的情况可以预处理出来。
【代码】
#include <cstdio>
#include <string>
#include <iostream> using namespace std; int t,n; struct node //用来建树的指针
{
node * next[4];
}; struct data //这是队列所记录的内容
{
string ss;
int kongge,step;//kongge是点号所在的位置,step是当前操作了多少步
}; node *root1,*root2; //root1是由广搜更新出的状态。root2记录的是目标状态
data team[1000000];//队列开到100W bool add_tree(node *root,string s) //把字符串s加入到某个树中(roo1 或 root2)
{
int l = s.size()-1; //我在字符串前有加一个空格,所以从1开始计数
node *p;
p = root;
bool flag = true;
for (int i = 1;i <= l;i++)
{
int t;
if (s[i] == '.') //点号则为3
t = 3;
else //否则按照字母顺序(就a和b,所以是1和2)
t= s[i]-'a'+1;
if (p->next[t] == NULL)//如果为空 表示没有出现过
{
flag = false; //记录没出现过
node *pp; //并创建一个新的节点
pp = new node;
for (int j = 1;j <= 3;j++)
pp->next[j] = NULL;
p->next[t] = pp;
p = p->next[t];
}
else
p = p->next[t]; //否则就顺着路往下走
}
return flag; //返回有没有出现过这个字符串
} void ex_change(char &a,char &b) //交换a和b两个字符
{
char t;
t = a;
a = b;
b = t;
} bool bfs(string s,int kongge) //bfs设计成bool型,便于判断有没有解
{
int head = 0,tail=1;
team[1].kongge = kongge; //记录空格的位置
team[1].ss = s; //这个字符串是什么
team[1].step = 0; //还有步骤数
while (head != tail)
{
head++;
string temp1 = team[head].ss;
int pd = team[head].kongge;
for (int i = 1;i <= 2*n-1;i++) //枚举需要交换哪些位置
{
if (temp1[i] != '.' && temp1[i+1]!='.') //如果两个位置都不是点号
{
string temp = team[head].ss;
ex_change(temp[i],temp[pd]);
ex_change(temp[i+1],temp[pd+1]); //交换
if (!add_tree(root1,temp)) //如果之前没有搜到过这个字符串
{
tail++; //把这个字符串加入到队列的尾端
team[tail].kongge = i;
team[tail].ss = temp;
team[tail].step = team[head].step + 1;
if (add_tree(root2,temp)) //如果这是目标状态
{
printf("%d\n",team[tail].step);
return true; //输出结果,同时返回有解
}
}
}
}
}
return false;//返回无解
} void input_data()
{
scanf("%d",&t);
for (int i = 1;i <= t;i++)
{
root1 = new node;
root2 = new node;
for (int j = 1;j <= 3;j++) //初始化根节点
root1->next[j] = NULL,root2->next[j] = NULL;
scanf("%d",&n);
char sss[100];
scanf("%s",sss); //用scanf输入,这样会比较快。
string s,ss;
ss = string(sss);
s = " ";
s+= ss;
ss = " ";
for (int j = 1;j <= 2*n;j++) //这是构造出目标状态
ss+='a'; //这个字母是随便写的。全是b也可以
for (int j = 1;j <= 2*n-1;j++) //枚举点号在什么位置
{
ss[j] = ss[j+1] = '.';//设为点号
int numa = 0;
for (int k = 1;k <= 2*n;k++) //不为点号则根据numa数目设为a或b
if (ss[k]!='.')
if (numa < n-1)
ss[k] = 'a',numa++;
else
ss[k] = 'b';
add_tree(root2,ss);//root2是目标状态的字典树
ss[j] = ss[j+1] = 'a';//回溯一下。
}
int p = s.find('.',0);//找到初始状态点号的位置。
add_tree(root1,s);
if (add_tree(root2,s))
{
printf("0\n");
continue;
}
if (!bfs(s,p))
printf("No Solution\n");
}
} int main()
{
//freopen("F:\\rush.txt","r",stdin);
input_data();
return 0;
}
【t008】钱币变换问题的更多相关文章
- BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1383 Solved: 582[Submit][St ...
- Hilbert-Huang Transform(希尔伯特-黄变换)
在我们正式开始讲解Hilbert-Huang Transform之前,不妨先来了解一下这一伟大算法的两位发明人和这一算法的应用领域 Section I 人物简介 希尔伯特:公认的数学界“无冕之王”,1 ...
- 【Win 10 应用开发】三维变换
所谓三维变换,其实是在二维平面上产生三维的视觉效果.前面老周简单提了一下透视效果,如果透视效果不能满需求,那可以考虑用三维变换. UIElement类有一个属性叫Transform3D,它定义的类型为 ...
- CSS3之3d变换与关键帧
3d变换是在transform基础上实现的 transform-style:preserve-3d; 建立3d空间 perspective:; 景深(设置用户看的距离) perspective-ori ...
- 纯CSS3实现多层云彩变换飞行动画
查看效果:http://hovertree.com/texiao/css3/4/效果2 效果图: 代码如下: <!doctype html> <html lang="zh& ...
- CSS3之过渡及2D变换
transition过渡 transition-duration:; 运动时间 transition-delay:; 延迟时间 transition-timing-function:; 运动形式 ea ...
- 为什么FFT时域补0后,经FFT变换就是频域进行内插?
应该这样来理解这个问题: 补0后的DFT(FFT是DFT的快速算法),实际上公式并没变,变化的只是频域项(如:补0前FFT计算得到的是m*2*pi/M处的频域值, 而补0后得到的是n*2*pi/N处的 ...
- 相机变换与Ray-Casting
p { margin-bottom: 0.1in; direction: ltr; line-height: 120%; text-align: justify; orphans: 0; widows ...
- 关于CSS3的小知识点之2D变换
transition过渡 transition-duration:; 运动时间 transition-delay:; 延迟时间 transition-timing-function:; 运动形 ...
随机推荐
- Log4j中为什么设计isDebugEnabled()方法
转自:https://www.jianshu.com/p/e1eb7ebfb21e 先看下面的代码,在真正执行logger.debug()之前,进行了logger.isDebugEnabled()的判 ...
- Flask项目之手机端租房网站的实战开发(十)
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...
- Excel数据比对-批量数据比对
1.导出现场的Excel收费规则2.有专门的代码写的测试收费规则的工具(开发自己开发的)3.在这个工具上选择,导出的收费规则Excel,点击导出按钮(导出按钮里面有计算每一列的计费结果4.Excel里 ...
- css实现简单的告警提示动画效果
需求:css实现简单的告警提示动画效果,当接收到实时信息的时候,页面弹出告警信息的动画效果 <!DOCTYPE html> <html lang="en"> ...
- 【例 7-12 UVA - 1343】The Rotation Game
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 迭代加深搜索. 每次抽动操作最多只会让中间那一块的区域离目标的"距离"减少1. 以这个作为剪枝. 枚举最大深度. ...
- Tomcat源代码阅读#1:classloader初始化
Bootstrap 通过Tomcat的启动脚本能够看到启动的入口是在Bootstrap,来看下Bootstrap的main方法, /** * Main method and entry point w ...
- js里的表格数组某个key去重
如Elemgnt的table绑定的数据要某个key是唯一的 var myarry = [ {name: 'liuyang',age :13}, {name:'jike',age:15}, {name: ...
- self.view.layer.contents 和 self.view.backgroundColor
一. self.view.layer.contents 和 self.view.backgroundColor 今天测了一下 : self.view.layer.contents 和 self. ...
- 【Codeforces Round #435 (Div. 2) C】Mahmoud and Ehab and the xor
[链接]h在这里写链接 [题意] 让你组成一个n个数的集合,使得这n个数的异或和为x; x<=1e5 每个数最大1e6; [题解] 1e5<=2^17<=2^18<=1e6的 ...
- Ajax之旅(二)--XMLHttpRequest
上文中提到的Ajax的异步更新.主要使用XMLHttpRequest对象来实现的,XMLHttpRequest对象能够在不向server提交整个页面的情况下,实现局部更新网页. 当页面所有载 ...