USACO Cowcycles 解题报告

这道题很侥幸地过了。基本就是按照题目(comment)说的逻辑做的。主要优化在于判断最大的ratio至少是最小的ratio的3倍这一点上。由于ratio = F / R,那么我们知道最大的ratio=max(F)/min(R),同理可得最小的ratio。这样可以提前判断ratio那个条件,如果不成立就跳过,免去了求每个ratio和sort的过程。

一个不主要,但是很重要的优化是把保存ratio, diff的数组定义放在循环外面。因为他们都是固定大小的,所以可以声明一次,覆盖写。这样做之后所有测试样例都能过了,于是也懒得再尝试其他优化了。


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

using namespace std;

void kofrange_recur(int cur, int remaining, int high, vector<vector<int> > &combinations, std::vector<int> partial)
{
	if (remaining == 0)
	{
		combinations.push_back(partial);
		return;
	}

	for (int i = cur; i <= high - remaining + 1; ++i)
	{
		partial.push_back(i);
		kofrange_recur(i + 1, remaining - 1, high, combinations, partial);
		partial.pop_back();
	}
}

std::vector<vector<int> > kofrange(int low, int high, int k)
{
	vector<vector<int> > combinations;
	kofrange_recur(low, k, high, combinations, std::vector<int>());
	return combinations;
}

void printCombinations(vector<vector<int> > &combinations)
{
	for (int i = 0; i < combinations.size(); ++i)
	{
		cout<<i<<":";
		for (int j = 0; j < combinations[i].size(); ++j)
		{
			cout<<combinations[i][j]<<"\t";
		}
		cout<<endl;
	}
}

int main()
{
	FILE *fin  = fopen("cowcycle.in", "r");
	FILE *fout = fopen("cowcycle.out", "w");
	
	int F, R;
	int F1, F2, R1, R2;
	fscanf(fin, "%d", &F);
	fscanf(fin, "%d", &R);
	fscanf(fin, "%d %d %d %d", &F1, &F2, &R1, &R2);

	// cout<<F<<" "<<R<<endl;
	// cout<<F1<<" "<<F2<<" "<<R1<<" "<<R2<<endl;
	vector<vector<int> > combF = kofrange(F1, F2, F);
	vector<vector<int> > combR = kofrange(R1, R2, R);
	// printCombinations(combinations);

	double minvariance = -1.0, minf = -1, minr = -1;
	std::vector<double> ratios(F * R, 0.0);
	std::vector<double> diff(F * R - 1, 0.0);

	for (int f = 0; f < combF.size(); ++f)
	{
		for (int r = 0; r < combR.size(); ++r)
		{
			// combF[f]
			// combR[r]
			if (1.0 * combF[f][combF[f].size() - 1] / combR[r][0] < 3.0 * combF[f][0] / combR[r][combR[r].size() - 1])
			{
				continue;
			}

			
			for (int i = 0; i < combF[f].size(); ++i)
			{
				for (int j = 0; j < combR[r].size(); ++j)
				{
					// ratios.push_back(((double)combF[f][i]) / combR[r][j]);
					ratios[i * R + j] = ((double)combF[f][i]) / combR[r][j];
				}
			}
			sort(ratios.begin(), ratios.end());
			
			// int nratios = ratios.size();
			// cout<<"[debug]suggest:"<<1.0 * combF[f][combF[f].size() - 1] / combR[r][0]<<", "<<1.0 * combF[f][0] / combR[r][combR[r].size() - 1]<<endl;
			// cout<<"[debug]reallly:"<<ratios[nratios - 1]<<", "<<ratios[0]<<endl<<endl;
			// if (ratios[nratios - 1] < ratios[0] * 3)
			// {
				// continue;
			// }
			
			for (int i = 0; i < ratios.size() - 1; ++i)
			{
				// diff.push_back(ratios[i + 1] - ratios[i]);
				diff[i] = ratios[i + 1] - ratios[i];
			}

			double sum = 0.0;
			for (int i = 0; i < diff.size(); ++i)
			{
				sum += diff[i];
			}
			double mean = sum / diff.size();

			sum = 0.0;
			for (int i = 0; i < diff.size(); ++i)
			{
				sum += (diff[i] - mean) * (diff[i] - mean);
			}
			double variance = sum / diff.size();

			if (minvariance < 0 || variance < minvariance)
			{
				minvariance = variance;
				minf = f;
				minr = r;
			}
		}
	}

	for (int i = 0; i < combF[minf].size(); ++i)
	{
		if (i != combF[minf].size() - 1)
		{
			fprintf(fout, "%d ", combF[minf][i]);
		}
		else
		{
			fprintf(fout, "%d\n", combF[minf][i]);	
		}
	}

	for (int i = 0; i < combR[minr].size(); ++i)
	{
		if (i != combR[minr].size() - 1)
		{
			fprintf(fout, "%d ", combR[minr][i]);
		}
		else
		{
			fprintf(fout, "%d\n", combR[minr][i]);	
		}
	}

	fclose(fin);
	fclose(fout);
	return 0;  
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值