首页 > 其他分享 >P2744 「USACO5.3」量取牛奶 Milk Measuring

P2744 「USACO5.3」量取牛奶 Milk Measuring

时间:2022-12-13 11:26:12浏览次数:40  
标签:Measuring P2744 NN pos USACO5.3 vec back now define

将桶按容积大小从小到大排序,令 \(f_{i,j}\) 表示前 \(i\) 个桶能否量出 \(j\) 夸脱,如果可以就用 vector 存储最优方案。

先枚举桶的种类再枚举夸脱数,转移看似只有两种:之前有或没有用过 \(i\) 号桶,新用一次 \(i\) 号桶。但这样是错误的,可能存在中间状态最优解长度较长的情况。具体例子可以看代码末尾。

所以我们还需要额外枚举用桶的次数而不是一次一次用,这样最优情况就不会被覆盖了。时间复杂度 \(O(Q^2\log P)\)。

考虑将桶按容积从大到小排序,令 \(f_{i,j}\) 表示前 \(i\) 个桶能否量出 \(j\) 夸脱,如果可以就令 \(g_{i,j}\) 表示最优方案需要桶的数量,\(used_{i,j}\) 表示最优方案有没有用 \(i\) 号桶。

这样我们就可以一次一次用了,最优解肯定不会被覆盖。

最后再根据记录的信息搜索一遍,\(\require{cancel}\require{enclose}\sout{O(kQ^2P\log P)}\) 跑得飞快,其中 \(k\) 取决于方案长度,很小很小。

#include<bits/stdc++.h>
using namespace std;
#define N 105
#define NN 20005
#define For(i,x,y)for(i=x;i<=(y);i++)
#define Down(i,x,y)for(i=x;i>=(y);i--)
int g[N][NN],c[N];
/*vector<int>h[N][NN];*/
bool used[N][NN],f[N][NN];
vector<int>print(int now,int pos)
{
	if(g[pos][now]==1)return{c[pos]};
	/*if(!h[pos][now].empty())return h[pos][now];*/
	int i,j,k;
	vector<int>vec,tmp;
	Down(i,pos-1,1)
	{
		j=now;
		while(j>=c[pos])
		{
			j-=c[pos];
			/*cerr<<i<<' '<<j<<' '<<pos<<' '<<now<<' '<<g[i][j]<<' '<<g[pos][now]<<endl;*/
			if(used[i][j]&&g[i][j]+1==g[pos][now])
			{
				tmp=print(j,i);
				if(vec.empty())vec=tmp;
				else
				{
					Down(k,vec.size()-1,0)
					if(vec[k]!=tmp[k])break;
					if(~k&&vec[k]>tmp[k])vec=tmp;
				}
			}
		}
		if(!vec.empty())
		{
			vec.push_back(c[pos]);
			/*h[pos][now]=vec;*/
			return vec;
		}
	}
}
int main()
{
	int Q,p,i,j;
	vector<int>vec;
	cin>>Q>>p;
	For(i,1,p)cin>>c[i];
	sort(c+1,c+p+1,greater<int>());
	f[0][0]=1;
	For(i,1,p)
	For(j,0,Q)
	if(j<c[i])
	{
		f[i][j]=f[i-1][j];
		g[i][j]=g[i-1][j];
		used[i][j]=0;
	}
	else
	{
		if(!f[i-1][j]&&!f[i][j-c[i]])continue;
		if(!f[i-1][j]||f[i-1][j]&&f[i][j-c[i]]&&g[i][j-c[i]]+1-used[i][j-c[i]]<=g[i-1][j])f[i][j]=used[i][j]=1,g[i][j]=g[i][j-c[i]]+1-used[i][j-c[i]];
		else
		{
			f[i][j]=1;
			used[i][j]=0;
			g[i][j]=g[i-1][j];
		}
	}
	cout<<g[p][Q]<<' ';
	Down(i,p,1)
	if(used[i][Q])break;
	vec=print(Q,i);
	Down(i,vec.size()-1,0)cout<<vec[i]<<' ';
	return 0;
}
//#include<bits/stdc++.h>
//using namespace std;
//#define N 105
//#define NN 20005
//#define For(i,x,y)for(i=x;i<=(y);i++)
//int c[N];
//bool f[N][NN];
//vector<int>vec[N][NN];
//bool pd(vector<int>&x,vector<int>&y)
//{
//	return x.size()<y.size()||x.size()==y.size()&&x<y;
//}
//int main()
//{
//	bool bo;
//	int Q,p,i,j,k;
//	cin>>Q>>p;
//	For(i,1,p)cin>>c[i];
//	sort(c+1,c+p+1);
//	f[0][0]=1;
//	For(i,1,p)
//	For(j,0,Q)
//	{
//		f[i][j]=f[i-1][j];
//		vec[i][j]=vec[i-1][j];
//		For(k,1,j/c[i])
//		if(f[i-1][j-c[i]*k])
//		{
//			vec[i-1][j-c[i]*k].push_back(c[i]);
//			if(!f[i][j]||pd(vec[i-1][j-c[i]*k],vec[i][j]))f[i][j]=1,vec[i][j]=vec[i-1][j-c[i]*k];
//			vec[i-1][j-c[i]*k].pop_back();
//		}
//		/*if(j>=c[i]&&f[i-1][j-c[i]])
//		{
//			vec[i-1][j-c[i]].push_back(c[i]);
//			if(!f[i][j]||pd(vec[i-1][j-c[i]],vec[i][j]))f[i][j]=1,vec[i][j]=vec[i-1][j-c[i]];
//			vec[i-1][j-c[i]].pop_back();
//		}
//		if(j>=c[i]&&f[i][j-c[i]])
//		{
//			bo=0;
//			if(vec[i][j-c[i]].empty()||vec[i][j-c[i]].back()<c[i])bo=1,vec[i][j-c[i]].push_back(c[i]);
//			if(!f[i][j]||pd(vec[i][j-c[i]],vec[i][j]))f[i][j]=1,vec[i][j]=vec[i][j-c[i]];
//			if(bo)vec[i][j-c[i]].pop_back();
//		}
//		if(i==1&&j==3)cerr<<vec[i][j].size()<<endl;*/
//	}
//	/*p=3;
//	Q=7247+949*1;
//	cerr<<f[p][Q]<<' ';*/
//	cout<<vec[p][Q].size();
//	For(i,0,int(vec[p][Q].size())-1)cout<<' '<<vec[p][Q][i];
//	return 0;
//}
/*
16737
4
904
909
916
949
*/

标签:Measuring,P2744,NN,pos,USACO5.3,vec,back,now,define
From: https://www.cnblogs.com/shanoamomoprprprprprprprprprprprprprprprprprprprpr/p/16978057.html

相关文章