题解 JSOI2010 找零钱的洁癖


题解 JSOI2010 找零钱的洁癖

题面

BZOJ

个人体会

van全没有思路...

只能去看题解...

还是个bfs+贪心

不管怎样竟然乱搞过了...

听M_sea小姐姐说她有更正经的做法(线性规划,网络流)?

解析

就是求最少的数加加减减得到\(X\).

考虑一波暴搜...

没了

开个map存一下当前的数经过没有.

最后和贪心比一下.

改错经历

一开始手写了一个Hash.

结果不知道为什么伪了...

然后用map过了...

另外还有数组开小(毕竟是搜索),循环边界写错导致RE的问题.

code

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <map>
#define ll long long
#define filein(a) freopen(a".cpp","r",stdin)
#define fileout(a) freopen(a".cpp","w",stdout);
using namespace std;

inline ll read(){
	ll sum=0,f=1;char c=getchar();
	while((c<'0'||c>'9')&&c!=EOF){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'&&c!=EOF){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}

const int N=1000003;
const int INF=0x7FFFFFFF;
int n;
ll X,c[N],s[N],a[N];
map<ll,bool> mp;

inline ll greedy(){
	ll ret=0,sum=X;
	for(int i=n;i;i--){
		if(!a[i]) continue;
		ret+=sum/a[i];
		sum-=sum/a[i]*a[i];
	}
	return sum? INF:ret;
}

inline ll bfs(){
	int hd=0,tl=1;
	s[1]=c[1]=0;
	while(hd<tl){
		hd++;
		for(int i=1;i<=n;i++){
			tl++;if(tl==N-22) return INF;
			s[tl]=s[hd]+1;
			c[tl]=c[hd]<X? c[hd]+a[i]:c[hd]-a[i];
			if(c[tl]==X) return s[tl];
			if(mp.count(c[tl])){tl--;continue;}
			mp[c[tl]]=1;
		}
	}
	return INF;
}

signed main(){
	X=read();
	while(scanf("%lld",&a[++n])!=EOF);
	sort(a+1,a+n+1);
	if(!X) puts("0");
	else printf("%lld\n",min(greedy(),bfs()));
	return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM