题意
题意:有一段 π km 长的行驶距离,在行驶图中用经纬线将地区划分成一个个区域,行驶的路线要求连续,可以是折线、曲线甚至闭合,问最多能通过多少个区域。
思路
思路:从题目易得,最少也可以经过四个区域,从一个点出发,我们可以移动微小的距离(小到不影响精度范围内,而且因为 π 是无理数,可以理解为其极后的一个数位发生了变动,可以不计)来直接访问周围的 4 个区域,显然,这是最优的。之后的路线我们可以选择沿 fi = min(w, d)到达一个新点,触发两个新区域,或者沿斜对角线 fj = sqrt(w × w + d × d)触发三个新区域。在这两种路线的选择上,最优解就是在满足 i × fi + j × fj <= pi 中找 2 × i + 3 × j 最大,用max函数不断更新最大值ans,for循环能开到最大能开到1000,因为T的范围最大到 1 0 5 10 ^5 105
做法
思维
不清醒,把ans设成了double…wa死了- 在两种情况的for循环中,注意 i 要从 0 开始。
for(int i = 0; i <= 1000; i++)
- 或者不用 if,直接两次for循环找最优解,也可以在一次for循环里完成。
ans = 0;
cin>>w>>d;
fi = min(w, d);
fj = sqrt(w * w + d * d);
for(int i = 0; i <= 100; i++)
{
if(pi - fi * i > 0) ans = max(ans, (int)((pi - i * fi) / fj) * 3 + 2 * i);
if(pi - fj * i > 0) ans = max(ans, (int)((pi - i * fj) / fi) * 2 + 3 * i);
}
cout<<ans + 4<<endl;
accode:
#include <bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
typedef long long ll;
#define pi acos(-1.0)
int main()
{
ios
int T;
double w, d, fi, fj;
int ans;
cin>>T;
while(T--)
{
ans = 4;
cin>>w>>d;
fi = min(w, d);
fj = sqrt(w * w + d * d);
if(fi / 2 > fj / 3)//获得同样收益时走斜对角线用的线少
{
for(int i = 0; i <= 1000; i++)
{
if(fi * i > pi) break;
int j = (pi - i * fi) / fj;
ans = max(ans, 2 * i + 3 * j + 4);
}
}
else
{
for(int i = 0; i <= 1000; i++)
{
if(fj * i > pi) break;
int j = (pi - fj * i) / fi;
ans = max(ans, 3 * i + j * 2 + 4);
}
}
cout<<ans<<endl;
}
return 0;
}
贪心
用贪心思想理解:一样先按照区域/代价比最优先选择方案,①如果选的是方案 1 走短边,那么在最后一次选择行驶方向时,看看是否能放弃短边,最后一次的短边长 fi 加上剩余的距离 pi - i × fi 看是否能改成走斜对角线,这样可以多增加一个区域。②如果选的是方案2走斜对角线,那么在最后一次选择行驶方向时,看看是否能放弃走斜对角线,将剩余的距离 pi - i × fj 改成走两次短边,这样可以增加一个区域。
accode:
#include <bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
typedef long long ll;
#define pi acos(-1.0)
int main()
{
ios
int T;
double w, d, fi, fj;
int ans;
cin>>T;
while(T--)
{
ans = 4;
cin>>w>>d;
fi = min(w, d);
fj = sqrt(w * w + d * d);
if(fi > pi)
{
cout<<ans<<endl;
}
else
{
if(fi / 2 < fj / 3)
{
int i = pi / fi;
ans += i * 2;
if(pi - (i-1) * fi > fj) ans++;
}
else
{
int i = pi / fj;
ans += i * 3;
if(pi - i * fj > fi) ans += 2;
else if(pi - (i-1) * fj > 2 * fi) ans++;
}
cout<<ans<<endl;
}
}
return 0;
}