IDA*:非常好用的搜索,可以解决很多深度浅,但是规模大的搜索问题。

估价函数设计思路:观察一步最多能向答案靠近多少。

埃及分数

题目大意:

  给出一个分数,由分子a 和分母b 构成,现在要你分解成一系列互不相同的单位分数(形如:1/a,即分子为1),要求:分解成的单位分数数量越少越好,如果数量一样,最小的那个单位分数越大越好。

如:

  19/45 = 1/3 + 1/12 + 1/180;

  19/45 = 1/5 + 1/6 + 1/18;

  以上两种分解方法都要3个单位分数,但下面一个的最小单位分数1/18比上一个1/180大,所以第二个更优。

题解:
dfs直接搜爆炸,因为深度无限。

bfs爆炸,空间不行。

所以,采用有深度限制的,并且不耗费空间的迭代加深搜索。

深度即分数的个数。

配合一下A*思想。

剪枝:

1.每次一步到达小于剩余分数的最小分母。

return b/a+1

2.如果当前可以选择的分数(已经是最大的)*剩下的步数<剩下的分数,return (A*思想)

3.如果只剩最后一步,直接判断能否取到。

对于不能取的处理,开一个数组记录。>1000都可以取的。

分数运算,手推式子。注意约分

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+;
ll a,b;
int k,T;
bool fl;
ll ans[N];
ll mem[N];
bool no[N];
int dp;
ll getfirst(ll a,ll b){
return b/a+;
}
bool cmp1(ll s1,ll m1,ll s2,ll m2){//s1/m1 > s2/m2 ?
return (ll)s1*m2>(ll)m1*s2;
}
bool cmp2(ll s1,ll m1,ll s2,ll m2){//s1/m1 >= s2/m2 ?
return (ll)s1*m2>=(ll)m1*s2;
}
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
void sub(ll &s1,ll &m1,ll s2,ll m2){
s1=s1*m2-s2*m1;
m1=m1*m2;
ll g=gcd(s1,m1);
s1/=g;
m1/=g;
}
bool better(){
for(int i=dp;i>=dp;i--){
if(mem[i]!=ans[i]){
//cout<<mem[i]<<" "<<ans[i]<<endl;
return (ans[i]==)||(mem[i]<ans[i]);
}
}
return false;
}
void dfs(int now,ll lim,ll rs,ll rm){
//if(dp<4) cout<<now<<" "<<lim<<" "<<rs<<" "<<rm<<endl;
if(now==dp){
if(rs==){
if(rm<lim) return;
//if(rm<=1000&&no[rm]) return;
fl=true;
//cout<<" ok "<<endl;
mem[dp]=rm;
if(better()){
///cout<<"better "<<endl;
for(int i=1;i<=dp;i++){
//cout<<mem[i]<<" ";
ans[i]=mem[i];
}//cout<<endl;
}
mem[dp]=;
}
return;
}
lim=max(lim,getfirst(rs,rm));
for(int i=lim;;i++){
if(cmp1(rs,rm,(dp-now+),i)) return;
if(cmp2(rs,rm,,i)){
ll hs=rs,hm=rm;
sub(hs,hm,,i);
mem[now]=i;
dfs(now+,i+,hs,hm);
mem[now]=;
}
}
}
int main(){
scanf("%lld%lld",&a,&b);
int t;
for(int i=;i<=k;i++){
scanf("%d",&t);
no[t]=;
}
fl=false;
while(!fl){
dp++;
//if(dp<4) cout<<dp<<endl;
dfs(,,(ll)a,(ll)b);
}
for(int i=;i<=dp;i++){
printf("%lld ",ans[i]);
}
return ;
}

The Rotation Game

每次8种选择吃不消。

迭代加深直接做。

A*估价:中间8个数,最多的那一个一次转动最多多一个。如果中间的8个最多的那一个和8的差距比剩余步数多,return

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=;
int mp[N][N];
int st[N][N];
char sta[],top;
char ans[],sum;
int dp,num;
bool fl;
int cnt[];
int fan[]={,,,,,,,,};
int fin(){
cnt[]=cnt[]=cnt[]=;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
cnt[mp[i][j]]++;
if(cnt[]==) return ;
if(cnt[]==) return ;
if(cnt[]==) return ;
}
int che(){
cnt[]=cnt[]=cnt[]=;
for(int i=;i<=;i++){
for(int j=;j<=;j++){
cnt[mp[i][j]]++;
}
}
int big=max(cnt[],max(cnt[],cnt[]));
return -big;
}
void mvh(int d){
if(d==){
int tmp=mp[][];
for(int i=;i>=;i--) mp[][i]=mp[][i-];
mp[][]=tmp;
}
else if(d==){
int tmp=mp[][];
for(int i=;i>=;i--) mp[][i]=mp[][i-];
mp[][]=tmp;
}
else if(d==){
int tmp=mp[][];
for(int i=;i<=;i++) mp[][i]=mp[][i+];
mp[][]=tmp;
}
else{
int tmp=mp[][];
for(int i=;i<=;i++) mp[][i]=mp[][i+];
mp[][]=tmp;
}
}
void mvz(int d){
if(d==){
int tmp=mp[][];
for(int i=;i<=;i++) mp[i][]=mp[i+][];
mp[][]=tmp;
}
else if(d==){
int tmp=mp[][];
for(int i=;i<=;i++) mp[i][]=mp[i+][];
mp[][]=tmp;
}
else if(d==){
int tmp=mp[][];
for(int i=;i>=;i--) mp[i][]=mp[i-][];
mp[][]=tmp;
}
else{
int tmp=mp[][];
for(int i=;i>=;i--) mp[i][]=mp[i-][];
mp[][]=tmp;
}
}
bool cmp(){
for(int i=;i<=dp;i++){
if(sta[i]<ans[i]) return true;
if(sta[i]>ans[i]) return false;
}
return false;
}
void dfs(int now,int las){
if(che()>dp-now+) return;
if(now==dp+){
if(che()==){
if(!fl){
memcpy(ans,sta,sizeof sta);
num=fin();
}
else if(cmp()){
memcpy(ans,sta,sizeof sta);
num=fin();
}
fl=true;
}
return;
}
for(int i=;i<=;i++){
if(i==fan[las]) continue;
if((i-)%>) mvh(i);
else mvz(i);
sta[++top]=i-+'A';
dfs(now+,i);
sta[top--]=' ';
if((fan[i]-)%>) mvh(fan[i]);
else mvz(fan[i]);
}
}
void clear(){
dp=;
fl=false;
}
int main(){
while(){
clear();
scanf("%d",&st[][]);
//cout<<"aa "<<endl;
if(st[][]==) break;
scanf("%d",&st[][]);
scanf("%d%d",&st[][],&st[][]);
for(int i=;i<=;i++) scanf("%d",&st[][i]);
scanf("%d%d",&st[][],&st[][]);
for(int i=;i<=;i++) scanf("%d",&st[][i]);
scanf("%d%d",&st[][],&st[][]);
scanf("%d%d",&st[][],&st[][]);
memcpy(mp,st,sizeof st);
if(che()==){
printf("No moves needed\n");
printf("%d\n",fin());
continue;
}
fl=false;
while(!fl){
dp++;
memcpy(mp,st,sizeof st);
dfs(,);
}
printf("%s\n",ans+);
printf("%d\n",num);
}
return ;
}

骑士精神

也许可以折半爆搜。

但是显然不够漂亮。

明显“超15步-1”,就迭代加深了。

估价函数:每次,骑士最多归位一个。如果算上最后一步的空格,可能归位2个。

所以,当前和终止的差距-1大于剩余步数的话,一定不行。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=;
int T;
char st[][];
int dp;
bool fl;
int nd[][]={
{,,,,,},
{,,,,,},
{,,,,,},
{,,,,,},
{,,,,,},
{,,,,,}
};
int mp[][];
int mv[][]={{-,+},{-,-},{-,+},{-,-},{+,+},{+,-},{+,-},{+,+}};
int che(int re){
int dif=;
for(int i=;i<=;i++){
for(int j=;j<=;j++){
dif+=(mp[i][j]!=nd[i][j]);
}
}
if(dif==) return ;
return dp-re+>=dif-;
}
void dfs(int now,int x,int y){
if(!che(now)) return;
if(fl) return;
if(now==dp+){
if(che(now)==) {
fl=true;return;
}
}
for(int i=;i<;i++){
int dx=x+mv[i][],dy=y+mv[i][];
if(dx<||dx>) continue;
if(dy<||dy>) continue;
swap(mp[x][y],mp[dx][dy]);
dfs(now+,dx,dy);
swap(mp[x][y],mp[dx][dy]);
}
}
void clear(){
fl=false;dp=;
}
int main(){
scanf("%d",&T);
while(T--){
clear();
int sx,sy;
for(int i=;i<=;i++){
scanf("%s",st[i]+);
for(int j=;j<=;j++){
if(isdigit(st[i][j]))mp[i][j]=st[i][j]-'';
else {
mp[i][j]=;sx=i,sy=j;
}
}
}
fl=false;
for(dp=;dp<=;dp++){
dfs(,sx,sy);
if(fl) break;
}
if(fl) printf("%d\n",dp);
else printf("-1\n");
}
return ;
}

埃及分数&&The Rotation Game&&骑士精神——IDA*的更多相关文章

  1. 『骑士精神 IDA*』

    骑士精神(SCOI2005) Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为1,纵 ...

  2. 【洛谷2324】[SCOI2005]骑士精神 IDA*

    [SCOI2005]骑士精神 描述 在一个\(5×5\)的棋盘上有\(12\)个白色的骑士和\(12\)个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为 ...

  3. [BZOJ 1085] [SCOI2005] 骑士精神 [ IDA* 搜索 ]

    题目链接 : BZOJ 1085 题目分析 : 本题中可能的状态会有 (2^24) * 25 种状态,需要使用优秀的搜索方式和一些优化技巧. 我使用的是 IDA* 搜索,从小到大枚举步数,每次 DFS ...

  4. bzoj 1085: [SCOI2005]骑士精神 IDA*

    题目链接 给一个图, 目标位置是确定的, 问你能否在15步之内达到目标位置. 因为只有15步, 所以直接ida* #include<bits/stdc++.h> using namespa ...

  5. bzoj1085 [SCOI2005]骑士精神——IDA*

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 搜索,IDA*,估价就是最少需要跳的步数: 代码意外地挺好写的,memcmp 用起来好 ...

  6. bzoj 1085 [SCOI2005]骑士精神——IDA*

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 迭代加深搜索. 估价函数是为了预计步数来剪枝,所以要优于实际步数. 没错,不是为了确定 ...

  7. 【日常学习】【IDA*】codevs2449 骑士精神题解

    题目描写叙述 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在不论什么时候一个骑士都能依照骑士的走法(它能够走到和它横坐标相差为1.纵坐标相差为2或 ...

  8. 1085. [SCOI2005]骑士精神【IDA※】

    Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2 ...

  9. BZOJ1085:[SCOI2005]骑士精神——题解+IDA*粗略讲解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1085 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空 ...

随机推荐

  1. java class file

    目录 什么是java类文件 幻数 主次版本号 常量池数和常量池 this_class super_class 接口数量和接口 字段数和字段 方法数和方法 以下内容主要还是参考<Inside JV ...

  2. CentOS安装输入法及kDE桌面

    参考教程:https://jingyan.baidu.com/article/154b46317fdfce28ca8f419e.html

  3. Altera FPGA AS,PS,Jtag配置模式区别

    Altera FPGA  AS,PS,Jtag配置模式区别 FPGA器件有三类配置下载方式:主动配置方式(AS)和被动配置方式(PS)和最常用的(JTAG)配置方式. AS模式(active seri ...

  4. 冲刺ing-5

    第五次Scrum冲刺 队员完成的任务 队员 完成任务 吴伟华 Leangoo的看板截图,燃尽图 蔺皓雯 编写博客 蔡晨旸 测试 曾茜 测试 鲁婧楠 测试 杨池宇 测试 成员遇到的问题 队员 问题 吴伟 ...

  5. MYSQL报警:Warning: Using a password on the command line interface can be insecure.

    问题描述:执行下面的语句,sql是执行成功了,但是出现了一个报警,报警看上去始终不舒服 mysql -hip -Pport -uuser -ppassword -e "use db;dele ...

  6. Python:迭代器的简单理解

    一.什么是迭代器 迭代,顾名思义就是重复做一些事很多次(就现在循环中做的那样).迭代器是实现了__next__()方法的对象(这个方法在调用时不需要任何参数),它是访问可迭代序列的一种方式,通常其从序 ...

  7. eclipse建包的一些细节

    com.a :com.b 等会先在com文件夹下在 建立 a,b两个子文件夹,引用路径时 不可"*\\com.a\\*"而是"*\\com\\a\\*"这点基础 ...

  8. lintcode-221-链表求和 II

    221-链表求和 II 假定用一个链表表示两个数,其中每个节点仅包含一个数字.假设这两个数的数字顺序排列,请设计一种方法将两个数相加,并将其结果表现为链表的形式. 样例 给出 6->1-> ...

  9. Java try catch

    /*   异常处理的捕捉形式: 这是可以对异常进行针对性处理的方式.   具体格式是: try { //需要被检测异常的代码. } catch(异常类 变量)//该变量用于接收发生的异常对象 { // ...

  10. Haproxy + Rabbit 集群 简要介绍

    # 两台主机都安装上rabbitMQ yum install -y rabbitmq-server   # 两台主机都配置/etc/hosts文件 192.168.23.10 rabbitmq1 19 ...