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 ...
随机推荐
- 示例:Servlet读取文件内容并在页面打印输出
package com.mhb; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; impo ...
- shell编程基础(3)条件判断语句
1,带参数的shellscript #this is program build 5.11 to test shell script ############ cxz ####### 5.11 ### ...
- python网络爬虫(一):网络爬虫科普与URL含义
1. 科普 通用搜索引擎处理的对象是互联网的网页,目前网页的数量数以亿计,所以搜索引擎面临的第一个问题是如何设计出高效的下载系统,已将海量的网页下载到本地,在本地形成互联网网页的镜像.网络爬虫 ...
- gcc编译代码报错及编译方式
一.error: 'for' loop initial declarations are only allowed in C99 mode 前段时间写了一个小C程序,放在linux下用gcc编译出错, ...
- navigationbar的一些设置记录
1.设置navigationbar背景颜色 [[UINavigationBar appearance] setBarTintColor:[UIColor blackColor]]; PS:如果颜色不对 ...
- class_create()
#define class_create(owner, name) \({ \ ...
- POJ2135 最小费用最大流模板题
练练最小费用最大流 此外此题也是一经典图论题 题意:找出两条从s到t的不同的路径,距离最短. 要注意:这里是无向边,要变成两条有向边 #include <cstdio> #include ...
- UVa 1262 (第k字典序) Password
题意: 给出两个6行5列的字母矩阵,一个密码满足:密码的第i个字母在两个字母矩阵的第i列均出现. 然后找出字典序为k的密码,如果不存在输出NO 分析: 我们先统计分别在每一列均在两个矩阵出现的字母,然 ...
- bzoj1834: [ZJOI2010]network 网络扩容
努力看了很久样例一直过不了...然后各种输出中间过程啊巴拉巴拉弄了1h,没办法了...然后突然想到啊原来的边可以用啊为什么不用...于是A了...感人肺腑 #include<cstdio> ...
- Raphael绘制圆圈环绕方法
$scope.toRadians = function (degrees) { return degrees * (Math.PI / 180); } $scope.toDegrees = funct ...