題解 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