这道题说了一长串背景,刚开始硬是没看懂。其实题意也是很简单的,就是在一个网格坐标系中,假设一小格的尺寸为1,然后给你个尺寸为N的图形,让你画个封闭的线条把这个图形包起来,在网格中,你只能画小方格的边或者对角线,并且每画一笔就要花费1分钟的时间。最后输出最小时间。
注意,所给的图形的形状可以自由变化。
我们先来找找规律。
首先尺寸为1,你可以这样围:,也可以这样:(这时我们选取第二种围法,即优先画出可围尺寸最大的线条,然后看看能不能把图形装进去)
尺寸为2(4min):尺寸为3(6min):尺寸为4(6min):
尺寸为5(7min):尺寸为6(8min):
其实这个线条的变化应该是这样的:
其中数字表示所需要的笔画次数。
所以不难发现笔画次数的变化从6开始每次都加1。那么线条所围图形的最大尺寸又是如何变化的呢?
从笔画为6开始,每次笔画加1,所围成的图形就会多一个梯形或者矩形,不难发现当笔画数为奇数时就是梯形,偶数就是矩形。
所以最大尺寸=上一个尺寸+梯形或矩形尺寸。而梯形和矩形的尺寸变化我们也可以发现,它是每出现两次后其底边长会加1。
若笔画数为t,那么(t>=6)为什么梯形和矩形的下标为t/4呢,首先是上个梯形与下个梯形之间间隔2个单位,其次每过2个梯形后其大小才会增长。
,
之后我采用打表的方法,所以这个式子没有继续往下推。
我的代码如下:
#include <cstdio>
using namespace std;
typedef unsigned long long ULL;
const int MAX=1e5+1;
int V[MAX];
int V_MAX;
void init_V()
{
ULL v=4;
for(int i=7;i<MAX;i++)
{
if(i&1)
v+=(i-3)/4;
else
v+=i/4*2-(i-4)/4;
V[i]=v;
if(v>1e9)
{
V_MAX=i;
break;
}
}
}
int bf(int n)
{
int low=7,high=V_MAX,mid;
while(low<=high)
{
mid=(low+high)/2;
if(n<V[mid])
high=mid-1;
else
low=mid+1;
}
if(n<=V[mid-1])
return mid-1;
if(n<=V[mid])
return mid;
else
return mid+1;
}
int main()
{
int t;
scanf("%d",&t);
init_V();
while(t--)
{
ULL n;
scanf("%I64u",&n);
if(n<=2)
printf("4\n");
else if(n<=4)
printf("6\n");
else
printf("%d\n",bf(n));
}
return 0;
}