<更新提示>

<第一次更新>


<正文>

Power Hungry Cows(POJ 1945)

Description

FJ的奶牛想要快速计算整数P的幂 (1 <= P <=20,000),它们需要你的帮助。因为计算极大数的幂,所以它们同一时间仅能使用2个存储器,每个存储器可记录某个结果值。 第一件工作是初始化存储器内的值一个为底数x, 另一个为1。 奶牛可以相乘或相除2个存储器中的值,并把结果存在其中某个存储器内,但所有存储的结果必须是整数。 例如, 如果他们想计算x^31, 一种计算方法是:

                                   WV1  WV2
开始: x 1
存储器1和存储器1相乘,结果存于存储器2: x x^2
存储器2和存储器2相乘,结果存于存储器2: x x^4
存储器2和存储器2相乘,结果存于存储器2: x x^8
存储器2和存储器2相乘,结果存于存储器2: x x^16
存储器2和存储器2相乘,结果存于存储器2: x x^32
存储器2除以存储器1,结果存于存储器2: x x^31

因此, x^31可以通过6次计算得出。给出要计算的幂次,要求求出最少需要几次计算。

Input Format

仅一个整数: P。

Output Format

仅一个整数:最少计算次数。

Sample Input

31

Sample Output

6

解析

如果考虑\(12\)种转移方式,花费均为\(1\),那么直接\(bfs\)是可以的,但是状态将达到\(12^{ans}\)之多,实际数据中,\(ans\)最大将达到\(18\)。

可以考虑设计一个估价函数,将\(bfs\)算法直接改进为\(A^*\)的启发式搜索算法。这个是比较容易想到的。设置状态\((a,b)\)代表第一个存储器指数为\(a\),第二个存储器指数为\(b\),令

\[f(state)=\min_{max(a,b)*2^{cnt}\geq p}\{cnt\}
\]

当\(max(a,b)\geq p\)时,\(f(state)=0\)。对于第一个式子,很好理解,当\(a\),\(b\)最大值小于\(p\)时,最小的计算次数就是成倍增长所要的次数,由于最后可能还需要减法微调,可以保证\(f(state)\geq g(state)\)。而对于第二个式子,由于减法我们无法保证,取\(f(state)=0\)即可。

这样的\(A^*\)算法可以得到\(42\)分。

剩下的测试点的错误的原因是\(MLE+TLE\),但导致它们原因是相同的:状态太多。

对于解决这个问题,最好的办法是剪枝,删去不优或无用状态。

可以考虑如下几个剪枝:

\(1.\)\((a,b)\)和\((b,a)\)是一样的,令\(a>b\),删去第二种状态

\(2.\)\((a,a)\)这个状态一定不如\((a,b)\),自乘自除可以达到一样的效果,直接删去

\(3.\)形如\((a,0)\)的状态,当\(a>p\)时,无解,直接删去

\(4.\)当\(p\%gcd(a,b) ≠ 0\)时,状态\((a,b)\)无解,直接删去

\(5.\)当\(a>p*2\)时,这个状态即使能得到解,计算次数也一定不是最优的,直接删去

加上一堆剪枝后,就能得到\(81\)分的高分了。

还有两个测试点还因为\(TLE\),而我们的思路\(A^*\)算法,记录计算次数的数组直接开二维是不行的,又因为状态稀疏,所以选择使用\(map\)。但是现在使用\(map\)的常数太大,需要改用\(hash\)表来存储。

这样就能完美解决本题了。

以下是几个有关\(A^*\)需要注意的地方:

\(1.\)一切\(A^*\)算法基于优先队列\(bfs\)算法,优先队列\(bfs\)要做的一切操作,\(A^*\)都要做,最容易被忽视的就是 "一个状态第一次被取出时就是最优解,所以一个状态只会拓展一次,但是一个状态的最优解可能会被更新多次",所以要开数组(\(map\)或\(hash\))记录到这个状态的最小花费。

\(2.\)\(A^*\)算法堆的排序关键字是当前花费加上未来预估花费,但是当两个状态的当前花费加上未来花费相同时,以未来花费为第二关键字,这对时间影响极大。

\(Code:\)

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
#define mset(name,val) memset(name,val,sizeof name)
#define filein(str) freopen(str".in","r",stdin)
#define fileout(str) freopen(str".out","w",stdout)
const int P=20020,SIZE=1000080;
int p,Head[P],cnt;
struct node
{
int next,val,s;
};
struct state
{
int a,b,f,s;
inline void fcost(void)
{
this->f = 0;
int Max = max( this->a , this->b );
while ( Max<p ) Max<<=1 , (this->f)++ ;
}
bool operator < (const state t)const
{
return this->s+this->f == t.s+t.f ? this->f < t.f : this->s+this->f < t.s+t.f ;
}
bool operator > (const state t)const
{
return this->s+this->f == t.s+t.f ? this->f > t.f : this->s+this->f > t.s+t.f ;
}
};
priority_queue < state,vector<state>,greater<state> > Heap;
state Begin;
node List[SIZE];
inline void input(void)
{
scanf("%d",&p);
Begin=(state){1,0,0,0};
}
inline int Hash(int x,int y)
{
return (int)(((long long)x*2023%SIZE+(long long)y*1926%SIZE)%SIZE);
}
inline bool retrieval(int val,int s)
{
int index=val%P;
for (int i=Head[index];i;i=List[i].next)
{
if (List[i].val==val)
{
if (List[i].s<=s)return true;
List[i].s=s;return false;
}
}
List[++cnt]=(node){Head[index],val,s};
Head[index]=cnt;
return false;
}
inline int gcd(int a,int b)
{
return b==0 ? a : gcd( b , a%b );
}
inline bool check(int x,int y)
{
return x==y || ( x>p && y==0 ) || p % gcd(x,y) || x>2*p ;
}
inline void transfer(int x,int y,int t)
{
if (x<y) swap(x,y);
if (check(x,y))return;
if (retrieval(Hash(x,y),t+1))return;
state next=(state){x,y,0,t+1};
next.fcost();
Heap.push(next);
}
inline int Astar(void)
{
Heap.push(Begin);
while (!Heap.empty())
{
state t=Heap.top();
Heap.pop();
if (t.a==p||t.b==p)return t.s;
int temp[2]={t.a,t.b};
for (int i=0;i<2;i++)
{
for (int j=i;j<2;j++)
{
for (int k=0;k<2;k++)
{
if (!k)
transfer(temp[i]+temp[j],temp[1],t.s);
if (k)
transfer(temp[0],temp[i]+temp[j],t.s);
}
}
}
transfer(temp[0],temp[0]-temp[1],t.s);
transfer(temp[0]-temp[1],temp[1],t.s);
}
}
int main(void)
{
filein("power");
fileout("power");
input();
printf("%d\n",Astar());
return 0;
}

<后记>

『Power Hungry Cows A*启发式搜索』的更多相关文章

  1. [USACO2002][poj1945]Power Hungry Cows(启发式搜索)

    Power Hungry CowsTime Limit: 1000MS Memory Limit: 30000K Total Submissions: 4570 Accepted: 1120 Desc ...

  2. 【BFS】Power Hungry Cows

    Power Hungry Cows Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5522   Accepted: 1384 ...

  3. poj 1945 Power Hungry Cows A*

    Description:     就是给你一个数,你可以把它自乘,也可以把他乘或除以任意一个造出过的数,问你最多经过多少次操作能变换成目标数 思路:这题真的不怎么会啊.n = 20000,每一层都有很 ...

  4. mongodb底层存储和索引原理——本质是文档数据库,无表设计,同时wiredTiger存储引擎支持文档级别的锁,MMAPv1引擎基于mmap,二级索引(二级是文档的存储位置信息『文件id + 文件内offset 』)

    MongoDB是面向文档的数据库管理系统DBMS(显然mongodb不是oracle那样的RDBMS,而仅仅是DBMS). 想想一下MySQL中没有任何关系型数据库的表,而由JSON类型的对象组成数据 ...

  5. BZOJ1669: [Usaco2006 Oct]Hungry Cows饥饿的奶牛

    1669: [Usaco2006 Oct]Hungry Cows饥饿的奶牛 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 665  Solved: 419 ...

  6. BZOJ 1669: [Usaco2006 Oct]Hungry Cows饥饿的奶牛( LIS )

    裸的LIS ----------------------------------------------------------------- #include<cstdio> #incl ...

  7. 『Python题库 - 填空题』151道Python笔试填空题

    『Python题库 - 填空题』Python笔试填空题 part 1. Python语言概述和Python开发环境配置 part 2. Python语言基本语法元素(变量,基本数据类型, 基础运算) ...

  8. 『Python题库 - 简答题』 Python中的基本概念 (121道)

    ## 『Python题库 - 简答题』 Python中的基本概念 1. Python和Java.PHP.C.C#.C++等其他语言的对比? 2. 简述解释型和编译型编程语言? 3. 代码中要修改不可变 ...

  9. Jmeter之『如果(If)控制器』

    判断方法 ${__jexl3("${projectName}"=="${targetDir}",)} ${__groovy("${projectNam ...

随机推荐

  1. 2.DNN-神经网络推导

    DNN就是我们常常说的深度神经网络,可以说由其衍生出来的各种深度算法都在AI界大行其道,今天就好好理一下这个算法.参考的是刘建平老师的博客:http://www.cnblogs.com/pinard/ ...

  2. java精确计算、精确计算工具类

    java精确计算 package org.aisino.erp.webservice.dzfp.util; import java.math.BigDecimal; public class Math ...

  3. leetcode刷题七<整数反转>

    给出一个 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 : 输入: 输出: 示例 : 输入: - 输出: - 示例 : 输入: 输出: 假设我们的环境只能存储得下 32 位的有符号整 ...

  4. Sublime Text3 & MinGW & LLVM CLang 安装配置C-C++编译环境

    Sublime Text是一款强大的跨平台代码编辑器,小巧而且丰富实用的功能是Visual Studio不能比拟的,但是编译运行是一个软肋,本文通过在sublime中配置g++编译器实现程序的编译功能 ...

  5. FunData — 电竞大数据系统架构演进

    电竞出现在人们视野中的频率越来越高了,此次选取FunData作为电竞数据平台,v1.0 beta版本主要提供由Valve公司出品的顶级MOBA类游戏DOTA2相关数据接口(详情:open.varena ...

  6. 操作系统PV编程题目总结一

    1.今有一个文件F供进程共享,现把这些进程分为A.B两组,规定同组的进程可以同时读文件F:但当有A组(或B组)的进程在读文件F时就不允许B组(或A组)的进程读文件F.试用P.V操作(记录型信号量)来进 ...

  7. 如何让pandas表格直接转换为markdown表格

    https://stackoverflow.com/questions/33181846/programmatically-convert-pandas-dataframe-to-markdown-t ...

  8. 记录一次DataTable排序的问题

    //dt.DefaultView.Sort = "字段名 方式"; 最开始用的上面的没好用,改成底下转换了一下就好用了0.0 DataView dv = new DataView( ...

  9. DirBuster工具扫描敏感文件

    DirBuster是一个多线程Java应用程序,旨在强制Web/应用程序服务器上的目录和文件名.它可以选择执行纯暴力,在查询隐藏文件和目录方面非常好用. 1)安装DirBuster 前提:电脑中必须安 ...

  10. ajax源代码

    //**********第一步, 获得一个xhr对象************* var xmlHttpReq = null; //声明一个空对象用来装入XMLHttpRequest if (windo ...