http://train.usaco.org/usacoprob2?a=lQZ5UB8ZNRK&S=cowcycle
题目大意:选出两组齿轮(数量分别不超过5个和10个),设前后轮齿数比为传动比,要求:1、最大传动比至少要是最小传动比的三倍 2、将传动比排序后相邻两者差(difference)的方差要最小
USACO总是出人意料,我原本以为会是一道超难的数学题或者构造题,再不济也得有个很酷的剪枝或是很厉害的规律,结果就是枚举尝试,还不如第一章里的虫洞。。。
/*
ID: frontie1
TASK: cowcycle
LANG: C++
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int F, R;
int f_st, f_ed, r_st, r_ed;
int f_gear[15], r_gear[15];
int f_output[20], r_output[20];
double output_var = 0x3f3f3f3f, tem_var;
double arr[100];
double dif[100];
int e = 0;
double total;
void DFS_r(int dep, int st, int ed)
{
if(dep == R){
//cout << "judge1 start" << endl;
if(3*f_gear[0]*r_gear[0] > f_gear[F-1]*r_gear[R-1]) return;
//cout << "get" << endl;
e = 0; total = 0;
for(int i = 0; i < F; ++i){
for(int k = 0; k < R; ++k){
arr[e++] = (double)f_gear[i] / r_gear[k];
}
}
sort(arr, arr+e);
for(int i = 1; i < e; ++i){
dif[i] = (arr[i]-arr[i-1]);
total += dif[i];
}
total /= (e-1);
tem_var = 0;
for(int i = 1; i < e; ++i){
tem_var += (dif[i] - total) * (dif[i] - total);
}
if(tem_var < output_var){
output_var = tem_var;
for(int i = 0; i < F; ++i){
f_output[i] = f_gear[i];
}
for(int i = 0; i < R; ++i){
r_output[i] = r_gear[i];
}
}
return;
}
else if(st > ed) return;
else{
for(int i = st; i <= ed; ++i){
r_gear[dep] = i;
DFS_r(dep+1, i+1, ed);
}
}
}
void DFS_f(int dep, int st, int ed)
{
if(dep == F){
//cout << "R start" << endl;
DFS_r(0, r_st, r_ed);
return;
}
else if(st > ed) return;
for(int i = st; i <= ed; ++i){
f_gear[dep] = i;
DFS_f(dep+1, i+1, ed);
}
}
int main()
{
freopen("cowcycle.in", "r", stdin);
freopen("cowcycle.out", "w", stdout);
cin >> F >> R;
cin >> f_st >> f_ed >> r_st >> r_ed;
DFS_f(0, f_st, f_ed);
for(int i = 0; i < F; ++i){
cout << f_output[i];
if(i != F-1) cout << ' ';
else cout << endl;
}
for(int i = 0; i < R; ++i){
cout << r_output[i];
if(i != R-1) cout << ' ';
else cout << endl;
}
return 0;
}
悄悄去看了USACO官方题解,原来还能哈希提速的,但是不想细看了,没有需求就没有动力(笑)