1. 程式人生 > >NKOJ P1628 嶽麓山提水【迭代加深】【揹包DP】

NKOJ P1628 嶽麓山提水【迭代加深】【揹包DP】

我們對選取的木桶種數進行限制(即列舉迭代加深中的層數),然後根據這個限制進行搜尋我們選擇哪些木桶,然後揹包驗證一下當前方案是否可行。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define sg string
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define repl(i,x,y) for(ll i=(x);i<(y);i++)
#define repd(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;

const ll N=2e5+5;
const ll Inf=1e18;

ll n,m,flag,v[N],f[N],ans[N];

inline ll read() {
	ll x=0;char ch=getchar();bool f=0;
	while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f?-x:x;
}

void dp(ll num) {
	memset(f,0,sizeof(f));f[0]=1;
	
	rep(i,1,num) rep(j,ans[i],n) f[j]|=f[j-ans[i]];
	
	if(f[n]) {
		flag=1;printf("%lld ",num);
		rep(i,1,num) printf("%lld ",ans[i]);
	}
}

void dfs(ll cur,ll cnt,ll num) {
	if(flag) return ;
	
	if(cnt==num) {
		dp(num);return ;
	}
	
	rep(i,cur+1,m) {
		ans[cnt+1]=v[i];
		dfs(cur+1,cnt+1,num);
		if(flag) return ;
	}
}

int main() {
//	freopen("nkoj1628.txt","r",stdin);
	
	n=read(),m=read();
	
	rep(i,1,m) v[i]=read();
	
	sort(v+1,v+1+m);
	
	rep(i,1,m) {
		dfs(0,0,i);
		
		if(flag) return 0;
	}

	return 0;
}