【2020-8-21】【数字游戏】【启发式搜索IDA*】
有这么一个游戏:
写出一个1~N的排列a[i],然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直到只剩下一个数字位置。下面是一个例子:
3 1 2 4
4 3 6
7 9
16
最后得到16这样一个数字。
现在想要倒着玩这样一个游戏,如果知道N,知道最后得到的数字的大小sum,请你求出最初序列a[i],为1~N的一个排列。若答案有多种可能,则输出字典序最小的那一个。 (n<12)
首先我们通过手算及暴力程序应该可以发现
设 sum 为最后一行的值
总共有 1 行 则 sum=a1*1
总共有 2 行 则 sum=a1*1+a2*1
总共有 3 行 则 sum=a1*1+a2*2+a3*1
总共有 4 行 则 sum=a1*1+a2*3+a3*3+a4*1
不难发现sum等于二项式定理中的系数乘上第n个数
所以对于这题我们只需要先预处理出二项式定理的系数 再对1~n进行dfs排列 适当加上一个剪枝就能AC

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long a[13],n,m,sum,b[13],last_num[13];
bool k[13],p;
void dfs(long long now,long long num,long long now_num)//当前位置 到当前位置的总和 当前位置的数值
{
if(p)//取到解就不必再继续dfs
return ;
if(now==n)
{
if(num==m)
{
for(long long i=1;i<=n;i++)
printf("%lld ",a[i]);
p=1;
return ;
}
else
{
k[now_num]=0;
return ;
}
} for(long long i=1;i<=n;i++)
{
if(!k[i])
{
if(num+i*b[now+1]>m)//一个小剪枝 如果总和大于所要的解则不再扩展
{
k[now_num]=0;
return;
}
else
{
k[i]=1;
a[now+1]=i;
dfs(now+1,num+i*b[now+1],i);
k[i]=0;//根据函数定义的回溯法求排列
}
}
}
}
int main()
{
scanf("%lld%lld",&n,&m);
for(long long i=1;i<=n;i++)
{
b[i]=1;
for(long long j=i-1;j>=1;j--)
b[j]+=b[j-1];
}
for(long long i=n;i>=1;i--)
{
last_num[i]=b[i]+last_num[i+1];
}
dfs(0,0,0);
}
n<12
对于原题中的n<12 我们的总和超过m就剪枝的做法是完全可以的
但教练提了一个n<20 的问题 这时一个剪枝就显得不足了(只能拿20分)
我们可以用IDA*的算法
即在dfs扩展时计算未来可能的代价 如果代价超出能忍受的范围则剪枝
我们考虑下面三个剪枝
剪枝一:
计算当前的“累加和”,若超出Sum,则没必要继续搜索
剪枝二:
计算当前的“累加和”+“未来的最小累加和”,若超出Sum,则没必要继续搜索
剪枝三:
计算当前的“累加和”+“未来的最大累加和”,若小于Sum,则没必要继续搜索
其中剪枝 二 三 就是对未来的一个估价函数

#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long a[21],n,m,sum,b[21],sort_num[21],pai[21],minm,maxm;
bool k[21],p,c;
void yugu(long long now)
{
pai[0]=0;
sort_num[0]=0;
maxm=0;
minm=0;
for(long long i=n/2+1;i>=now;i--)
pai[++pai[0]]=b[i];
for(long long i=n/2+2;i<=n;i++)
pai[++pai[0]]=b[i];
for(long long i=1;i<=n;i++)
{
if(!k[i])
sort_num[++sort_num[0]]=i;
}
for(long long i=1;i<=sort_num[0];i++)
{
minm+=sort_num[i]*pai[i];
maxm+=sort_num[i]*pai[sort_num[0]-i+1];
}
}
void dfs(long long now,long long num)
{ if(c)
return ;
if(num>m)
return ;
yugu(now+1);//进行预估代价
if(num+maxm<m||num+minm>m)//判断是否可行剪枝
return ;
if(now==n)
{
if(num==m)
{
for(long long i=1;i<=n;i++)
printf("%lld ",a[i]);
c=1;
return ;
}
else
return ;
}
for(long long i=1;i<=n;i++)
{ if(!c)
if(!k[i])
{
if(num+i*b[now+1]>m)
continue;
else
{
k[i]=1;
a[now+1]=i;
dfs(now+1,num+i*b[now+1]);
k[i]=0;
}
}
}
}
int main()
{
// freopen("szyx.in","r",stdin);
// freopen("szyx.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(long long i=1;i<=n;i++)
{
b[i]=1;
for(long long j=i-1;j>=1;j--)
b[j]+=b[j-1];
}
dfs(0,0);
return 0;
}
启发式搜索 IDA*
【2020-8-21】【数字游戏】【启发式搜索IDA*】的更多相关文章
- Python代码实现猜数字游戏
1 # -*- coding:utf-8 -*- 2 # 作者:IT小学生蔡坨坨 3 # 时间:2020/12/9 23:02 4 5 # 猜数字游戏: 6 # 代码中生成一个随机整数. 7 # 然后 ...
- NOIP2003pj数字游戏[环形DP]
题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分 ...
- [Noip2003 PJ] 数字游戏
Description & Range 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有 ...
- codevs 1085 数字游戏 dp或者暴搜
1085 数字游戏 2003年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单 ...
- Poj 2328 Guessing Game(猜数字游戏)
一.题目大意 两个小盆友玩猜数字游戏,一个小盆友心里想着1~10中的一个数字,另一个小盆友猜.如果猜的数字比实际的大,则告诉他"too high",小则"too low& ...
- Codevs 1085 数字游戏
1085 数字游戏 2003年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 丁丁最近沉迷于一个数字游戏之中 ...
- 【dp】数字游戏&寒假祭
区间DP 题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按 ...
- luogu P1043 数字游戏
题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分 ...
- 数字游戏(codevs 1085)
题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共 ...
随机推荐
- Billu_b0x2内网渗透(多种提权方法)靶场-vulnhub
个人博客阅读体验更佳 本次来试玩一下vulnhub上的Billu_b0x2,下载地址. 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware可能存在兼容性问题.靶场推荐使用N ...
- MeteoInfo-Java解析与绘图教程(五)
MeteoInfo-Java解析与绘图教程(五) 最近太忙了,终于有时间继续写了,上文说到了基本上的绘图方法,但缺少色阶呈现,一般图叠加着地图上,后端不需要管色阶,但也要注意web页面色阶和我们的生成 ...
- 解决更新页面版本后用户需CTRL+F5强刷才能应用最新页面
设置文件永远不从缓存读取 第一步:在html文件设置文件不缓存 <!DOCTYPE html> <html lang="en" class="theme ...
- 8.5(337)——树形dp
将题目进行翻译,就是遍历二叉树算出最大权值,在遍历过程中,不能同时选择两个相连的节点. 第一种子问题的构造,是以爷爷--父亲--孙子的"三代"节点一同构造的,将最优子问题的结构定义 ...
- 【UE4 设计模式】命令模式 Command Pattern
概述 描述 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作. 命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务 ...
- OO2020 助教工作总结
1 我的初衷 这一学期的OO助教工作是我一段宝贵的经历,在其中我学习了很多.见识了很多,收获满满.当时报名OO的初衷主要有三方面.首先,我想说OO是我所上过的最好的一门课之一,这门课有这一套从理论讲授 ...
- 大闸蟹的OO第二单元总结
OO的第二单元是讲多线程的协作与控制,三次作业分别为FAFS电梯,ALS电梯和三部需要协作的电梯.三次作业由浅入深,让我们逐渐理解多线程的工作原理和运行状况. 第一次作业: 第一次作业是傻瓜电梯,也就 ...
- mbps和MB/s是怎么换算的
Mbps即"传输速率",也叫"带宽".去营业厅开网线的时候会问开几兆的宽带,这里说的"几兆的宽带"就是指多少Mbps,但是Mbps和MB/s ...
- 零基础如何更好的学习Linux
本节旨在介绍对于初学者如何学习 Linux 的建议.如果你已经确定对 Linux 产生了兴趣,那么接下来我们介绍一下学习 Linux 的方法. 如何去学习 学习大多类似庖丁解牛,对事物的认识一般都是由 ...
- 攻防世界 杂项 1.base64÷4
666C61677B45333342374644384133423834314341393639394544444241323442363041417D 根据题目base64÷4得base16 在线工 ...