USACO Milk Measuring 解题报告

这道题我是用一个数组记录每个 q (1~Q)的最好组成(之后看标准答案,这里的空间复杂度可以降低的,即记录“前一个"是谁和最后增加的那个,可以回溯回去)。然后类似dijkstra(基本就是Dijkstra),从当前最好的组成向外扩展。扩展的时候从当前组成的下一个没用的pail开始,每个pail都增加到Q为止。这些q都放在一个priority_queue里面。 如果出队的是Q,那么任务就完成了。

注:C++ STL中priority_queue的第三个参数,即比较函数,应该是如果第一个比第二个大,就返回true.似乎也不存在自己和自己比较的情况(和sort的第三个参数感觉不一样)。

Executing...
   Test 1: TEST OK [0.005 secs, 3504 KB]
   Test 2: TEST OK [0.005 secs, 3504 KB]
   Test 3: TEST OK [0.003 secs, 3504 KB]
   Test 4: TEST OK [0.005 secs, 3504 KB]
   Test 5: TEST OK [0.003 secs, 3504 KB]
   Test 6: TEST OK [0.046 secs, 3768 KB]
   Test 7: TEST OK [0.065 secs, 3504 KB]
   Test 8: TEST OK [0.459 secs, 3768 KB]
   Test 9: TEST OK [0.132 secs, 3768 KB]
   Test 10: TEST OK [0.594 secs, 3768 KB]

All tests OK.

/* 
ID: thestor1
LANG: C++
TASK: milk4
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <climits>
#include <cassert>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

vector<vector<int> > combinations(20000 + 1, vector<int>());

class cmpbycombinations
{
public:
	bool operator() (const int& lhs, const int&rhs) const
	{
		// cout<<"[debug]"<<lhs<<" vs "<<rhs<<":";

		if (combinations[lhs].size() < combinations[rhs].size())
		{
			// cout<<"false"<<endl;
			return false;
		}
		else if (combinations[lhs].size() == combinations[rhs].size())
		{
			for (int i = 0; i < combinations[lhs].size(); ++i)
			{
				if (combinations[lhs][i] < combinations[rhs][i])
				{
					// cout<<"false"<<endl;
					return false;
				}
				else if (combinations[lhs][i] > combinations[rhs][i])
				{
					// cout<<"true"<<endl;
					return true;
				}
			}
		}
		else
		{
			// cout<<"true"<<endl;
			return true;
		}
		if (lhs < rhs)
		{
			// cout<<"false"<<endl;
			return false;
		}
		else
		{
			// cout<<"true"<<endl;
			return true;	
		}
	}
};

bool smaller(std::vector<int> &newcomb, std::vector<int> comb)
{
	if (newcomb.size() < comb.size())
	{
		return true;
	}
	else if (newcomb.size() > comb.size())
	{
		return false;
	}
	else
	{
		for (int i = 0; i < newcomb.size(); ++i)
		{
			if (newcomb[i] < comb[i])
			{
				return true;
			}
			else if (newcomb[i] > comb[i])
			{
				return false;
			}
		}
		return false;
	}
}

int main()
{
	ifstream fin("milk4.in");
	ofstream fout("milk4.out");

	int Q;
	fin>>Q;
	int P;
	fin>>P;
	vector<int> pails(P);
	for (int i = 0; i < P; ++i)
	{
		fin>>pails[i];
	}
	sort(pails.begin(), pails.end());

	priority_queue<int, vector<int>, cmpbycombinations> que;
	
	for (int i = 0; i < pails.size(); ++i)
	{
		for (int j = 1; j <= Q; ++j)
		{
			if (combinations[j].size() == 0 && j % pails[i] == 0)
			{
				combinations[j].push_back(i);
				que.push(j);
				// cout<<"[debug]"<<j<<" push"<<endl;
				// for (int k = 0; k < combinations[j].size(); ++k)
				// {
					// cout<<pails[combinations[j][k]]<<"\t";
				// }
				// cout<<endl;
			}
		}
		// if (combinations[pails[i]].size() == 0)
		// {
			// combinations[pails[i]].push_back(i);
			// que.push(pails[i]);
			
			// cout<<"[debug]"<<pails[i]<<" push"<<endl;
			// for (int k = 0; k < combinations[pails[i]].size(); ++k)
			// {
			// 	cout<<pails[combinations[pails[i]][k]]<<"\t";
			// }
			// cout<<endl;
		// }
	}

	while (!que.empty())
	{
		int q = que.top();
		
		// cout<<"[debug]"<<q<<" pop"<<endl;
		// for (int k = 0; k < combinations[q].size(); ++k)
		// {
		// 	cout<<pails[combinations[q][k]]<<"\t";
		// }
		// cout<<endl;

		que.pop();
		if (q == Q)
		{
			break;		
		}
		assert(combinations[q].size() != 0);
		int last = combinations[q][combinations[q].size() - 1];
		// if (combinations[q].size() == 1 && pails[last] == 1025)
		// {
		// 	cout<<"[debug]"<<endl;
		// }
		int next = last + 1;
		while (next < pails.size())
		{
			std::vector<int> newcomb = combinations[q];
			newcomb.push_back(next);

			int nq = q + pails[next];
			while (nq <= Q)
			{
				if (combinations[nq].size() == 0 || smaller(newcomb, combinations[nq]))
				{
					// combinations[nq] = combinations[q];
					// // if (next != last)
					// // {
					// combinations[nq].push_back(next);
					combinations[nq] = newcomb;
					// }
					
					// cout<<"[debug]"<<nq<<" push"<<endl;
					// for (int k = 0; k < combinations[nq].size(); ++k)
					// {
						// cout<<pails[combinations[nq][k]]<<"\t";
					// }
					// cout<<endl;

					que.push(nq);
				}
				nq += pails[next];
			}
			next++;
		}
	}

	assert(combinations[Q].size() != 0);

	fout<<combinations[Q].size();
	for (int i = 0; i < combinations[Q].size(); ++i)
	{
		fout<<" "<<pails[combinations[Q][i]];
	}
	fout<<endl;
	
	fin.close();
	fout.close();
	return 0;  
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值