[vijos 1599]: 货币(记忆化搜索+hash优化) 2017-06-08 16:23 57人阅读 评论(0) 收藏

背景

又是一道水题

描述

在某个神秘的星球上有一种货币,它有一种奇怪的兑换规则
你有且仅有一枚面值为n的金币,你可以去银行进行兑换,也可以不兑换
如果去银行兑换,兑换的规则是这样的:用面值为a的金币去兑换可以换到a/2,a/3,a/4这三枚硬币(如果
是小数则截尾取整),你可以兑换多次
读入n
输出你最后最多能拥有的钱数w
每个测试点中有T组数据

格式

输入格式

一个数T表示该点的测试数据组数(1=<T<=20 )
下面跟着T行,每行一个整数n(0 <= n <= 1000000000 )

输出格式

输出T行(一一对应)
每行一个整数就是你最后最多拥有的钱数w

样例1

样例输入1

2
12
2

样例输出1

13
2

限制

各个测试点3s

提示

小心数据较大,但是不需要高精度

来源

源于spoj

思路 

记忆化搜索 因为最大到10^9 所以数组肯定是不够开的 

这个时候就要 hash优化了

首先 朴素解法只过一个点 20分

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define N 10000000
#define ll long long 
using namespace std;
int f[N];
ll dfs(int x){
	if(f[x]) return f[x];
	int t=dfs(x/2)+dfs(x/3)+dfs(x/4);
	return f[x]=t>x?t:x;
}
int main(){
	for(int i=0;i<=8;i++)
		f[i]=i;
	int T;
	scanf("%d",&T);
	int n;
	while(T--)
	scanf("%d",&n),printf("%lld
",dfs(n));
	return 0;
} 
hash优化 说明详细见上一篇博客 传送

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<malloc.h>
#define M 10017
#define ll long long
using namespace std;
struct node{
	int s;
	ll v;
	struct node *next; 
}*a[M];
ll dfs(ll x){
	struct node *p;
	p=a[x%M];
	while(p!=NULL){
		int k=p->s;
		if(k==x) return p->v;
		p=p->next;
	} 
	ll ans;
	if(x<=11) ans=x;
	else {
		ll	t=dfs(x/2)+dfs(x/3)+dfs(x/4);
		if(x<t) ans=t;else ans=x;
	}
	struct node *q; 
	q=(struct node*)malloc(sizeof(struct node));
	q->s=x;
	q->v=ans;
	q->next=a[x%M];
	a[x%M]=q;
	return ans;
} 
int main(){
	int T,n;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		printf("%lld
",dfs(n));
	}
	return 0;
} 


原文地址:https://www.cnblogs.com/xljxlj/p/7183619.html