Uva 11198 - Dancing Digits
Problem D
Dancing Digits
题目意思:
给你{1,2,3,4,5,6,7,8}的一个排列,其中每个数带负号或带正号,通过插入的方法将这些数按绝对值从小到大排序,输出插入的最小步数,如果不可能完成输出-1,能否插入的要求是:你要根据其余的一个数嵌入其左边或右边,这个数跟你要插入的数不同符号,且绝对值相加必须得是素数,所以根据一个数为中心你可以插入其左或其右。
解题思路:
#BFS+Hash# 哈希选择了康托展开,用队列存储每一个状态,且用visit[对应哈希值]表示是否已访问过。思路清晰 了就好办,主要是看状态转移的时候是怎样一个转移法,首先要顾及每一个数共需要两个for循环,把每两个数都判断一遍,判断的要求就是一正一负,绝对值相加是素数,然后还要分情况放左边还是右边,我花的时间主要是在写插入函数那里,具体思路看代码实现(画图找规律是王道啊)。一开始你得判断几个特殊情况。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define MAXN 40322
#define SIZE 8
using namespace std; typedef int State[SIZE];
typedef struct Status{
State value;
}Status; queue<Status>queuing; int st[MAXN];
bool visit[MAXN];
bool Prime[*SIZE];
int factory[] = {, , , , , , , , };
int start = -;
int dir[] = {, -};
int input[SIZE]; void getPrime()
{//存储需要的素数
memset(Prime, false, sizeof(Prime));
for(int i=; i<*SIZE; ++i)
{
if(!Prime[i])
{
for(int j=i+i; j<*SIZE; j += i)
Prime[j] = true;
}
}
return;
} int try_to_insert(int s[])
{//返回对应的康托展开
int sum = ;
for(int i=; i<SIZE; ++i)
{
int cnt = ;
for(int j=i+; j<SIZE; ++j)
if(fabs(s[i])>fabs(s[j])) ++cnt;
sum += cnt*factory[SIZE-i-];
}
return sum;
} bool isExchange(int a, int b)
{//判断两个对应的数能否插入,可以返回true否则false if((a> && b<) || (a< && b>))
{
if(a>) b = -b;
else a = -a;
if(!Prime[a+b]) return true;
}
return false;
} void Translate(int s[], int to, int from, int kind)
{//插入的函数,kind = -1 表示from位置的数插入到to位置的左边,kind = 1 表示插入到to位置的右边
State p;
int temp_to = s[to], temp_from = s[from];
bool flag = false;
s[to] = s[from] = ;
if(kind == -)
{
for(int i=SIZE-, j=SIZE-; i>=; )
{
if(s[j] != ) p[i--] = s[j--];
else if(flag == false)
{
if(to > from)
{
p[i--] = temp_to;
p[i--] = temp_from;
}
j--;
flag = true;
}
else
{
if(to < from)
{
p[i--] = temp_to;
p[i--] = temp_from;
}
j--;
}
}
}
else
{
for(int i=, j=; i<SIZE; )
{
if(s[j] != ) p[i++] = s[j++];
else if(flag == false)
{
if(to < from)
{
p[i++] = temp_to;
p[i++] = temp_from;
}
j++;
flag = true;
}
else
{
if(to > from)
{
p[i++] = temp_to;
p[i++] = temp_from;
}
j++;
}
}
}
memcpy(s, p, sizeof(p));
return;
} bool Traverse()
{
memset(visit, false, sizeof(visit));
visit[start] = true;
st[start] = ;
Status init;
memcpy(init.value, input, sizeof(input));
queuing.push(init);
while(!queuing.empty())
{
Status ss = queuing.front();
State& s = ss.value;
int elem = try_to_insert(s);
queuing.pop();
//两个for循环加上两种插入的情况
for(int i=; i<SIZE; ++i)
{
for(int j=; j<SIZE; ++j)
{
if(isExchange(s[i], s[j]))
{
Status tt;
State& t = tt.value;
for(int z=; z<; ++z)
{
memcpy(t, s, sizeof(t));
if(i+dir[z] != j)
{
Translate(t, i, j, dir[z]);
int step = try_to_insert(t);
if(!visit[step])
{
visit[step] = true;
st[step] = st[elem]+;
queuing.push(tt);
if(step == )
{//step == 0 表示到达了已排序的状态则返回
return true;
}
}
}
}
}
}
}
}
return false;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("F:\\test\\input.txt", "r", stdin);
#endif
getPrime();
int T = ;
while(cin>>input[] && input[])
{
int flag = ;
if(input[] > ) flag++; for(int i=; i<SIZE; ++i)
{
cin>>input[i];
if(input[i] > ) flag++;
}
start = try_to_insert(input);
cout<<"Case "<<++T<<": ";
if (start == )
{
cout<<""<<endl;
continue;
}
if (flag == SIZE || !flag)
{
cout<<"-1"<<endl;
continue;
}
if(Traverse()) cout<<st[]<<endl;
else cout<<"-1"<<endl; while(!queuing.empty()) queuing.pop();
}
return ;
}
Uva 11198 - Dancing Digits的更多相关文章
- UVA 1341 - Different Digits(数论)
UVA 1341 - Different Digits 题目链接 题意:给定一个正整数n.求一个kn使得kn上用的数字最少.假设同样,则输出值最小的 思路: 首先利用鸽笼原理证明最多须要2个数字去组成 ...
- UVa - 11452 - Dancing the Cheeky-Cheeky
先上题目: F. Dancing the Cheeky-Cheeky Context The Cheeky-Cheeky is a new song. They dance it in Mula, ...
- UVA题目分类
题目 Volume 0. Getting Started 开始10055 - Hashmat the Brave Warrior 10071 - Back to High School Physics ...
- uva 993 Product of digits (贪心 + 分解因子)
Product of digits For a given non-negative integer number N , find the minimal natural Q such tha ...
- UVa 993: Product of digits
这道题很简单.先将N用2,3,5,7(即10以内的素数)分解因数(需要先特殊判断N不为1),然后将可以合并的因数合并(如2*2合并成4,)这样求得的结果位数会减少,大小肯定会小一些.具体实现见代码. ...
- uva 10061 How many zero's and how many digits ?
How many zeros and how many digits? Input: standard input Output: standard output Given a decimal in ...
- How many zero's and how many digits ? UVA - 10061
Given a decimal integer number you will have to find out how many trailing zeros will be there in it ...
- UVA - 10061 How many zero's and how many digits ?
n!=x*b^y, 当x为正整数时,最大的y就是n!末尾0的个数了, 把n,b分别拆成素因子相乘的形式: 比如, n=5,b=16 n=5,b=2^4, 非常明显,末尾0的个数为0 10进制时,n!= ...
- UVA 10061 How many zero's and how many digits ? (m进制,阶乘位数,阶乘后缀0)
题意: 给出两个数字a和b,求a的阶乘转换成b进制后,输出 (1)后缀中有多少个连续的0? (2)数a的b进制表示法中有多少位? 思路:逐个问题解决. 设a!=k. k暂时不用直接转成b进制. (1 ...
随机推荐
- RMI
Java RMI (Remote Method Invocation 远程方法调用)是用Java在JDK1.1中实现的,它大大增强了Java开发分布式应用的能力.Java作为一种风靡一时的网络开发语言 ...
- libsvm+detector_(libsvm参数说明)
细分析了cvhop.cpp中的compute函数,可以直接调用它来获得样本HOG,然后训练得到检测算子 1.制作样本2.对每一张图片调用hog.compute(img, descriptors,Siz ...
- 预定义的类型“Microsoft.CSharp.RuntimeBinder.Binder”未定义或未导入
http://www.mzwu.com/article.asp?id=3611 因为新加了Microsoft.CSharp的引用, 只需要重新生成一下项目,就可以消除这个错误提示
- oj放苹果
题目描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. 输入 每个用例包含二个整数M和N.0<=m< ...
- build path功能详解
在项目上右键>Build path>Config build path “web project”中,一般把"src"设置为source folder,把WEB-INF ...
- vs2008 编译时候 自动关闭 问题解决方法
最近又出现如此让人崩溃的问题. vs2008在编译程序时候老是莫名其妙的自动退出.卸载重装以后问题仍然存在. 害我一度以为是vs2008的BUG,看网上说的更新BUG. ...
- UVa 1152 4 Values whose Sum is 0
题意:给出n,四个集合a,b,c,d每个集合分别有n个数,分别从a,b,c,d中选取一个数相加,问使得a+b+c+d=0的选法有多少种 看的紫书,先试着用hash写了一下, 是用hash[]记录下来a ...
- EF DataBase First生成model的验证
如何避免在EF自动生成的model中的DataAnnotation被覆盖掉 相信很多人刚接触EF+MVC的时候,DataBase First模式生成model类中加验证信息的时候,会在重新生成mode ...
- Eclipse @override报错解决 必须覆盖超类方法
解决办法:Windows->Preferences-->java->Compiler-->compiler compliance level设置成1.6
- json格式的字符串使用string.Format()方法报错:输入字符串的格式不正确
解决:把大括号转义一下就可以了啊,大括号的转义是两个{{ 结尾是}} 今天看同事写的代码,发现他在使用string.format拼接类似json格式的数据时,大括号多了一对,感觉不对就查了查 ...