NOI Online #2入门组
A 未了
题目描述
由于触犯天神,Sisyphus 将要接受惩罚。
宙斯命令Sisyphus推一块儿巨石上长度为L的山坡。Sisyphus匀速向上推的速度为每年v的长度(由于是匀速, 故经过1/2年将能向上推v/2的长度)。然而, 宙斯并不希望Sisyphus太快到达山顶。宙斯可以施展n个魔法, 若他施展第i个魔法, 那么Sisphus第一次到达位置ai时, 他将会同巨石一起滚落山底, 并从头推起。(滚落的时间忽略不计, 即可看做第一次到达位置ai后, Sisyphus立即从山地重新出发)
现在, 宙斯有q个询问。每个询问ti, 他want to know, 他最少需要实战多少个魔法才能使Sisphus到达山顶所用的年数大于ti。
题目思路
根据题目描述, 使用第i个魔法相当于多走了a[i]的路, 路越长, 时间越长, 所以根据贪心思想, 因为要求最少使用的魔法数量, 假设长度不变, 那么取得魔法增加的路程越长, 数量就越少, 根据这个, 我们可以排序, 然后算出前i个魔法使用后的时间,(排好序后, 取前i个一定是最优方案)。
下面, 就是取多少个的问题了。
显然, 数列满足单调性(因为排序了呗), 二分即可。
详细内容见代码
代码
double L, v;
double a[N];
double b[N];
long long a;
//b[i] 表示使用前i个魔法后爬上山顶所用的时间
bool cmp(int a, int b)
{
return a > b;}
int main()
{
cin >> n >> L >> v;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
sort(a+1, a+n+1, cmp);//魔法长度从大到小排序:贪心
b[0] = L / v//t = s / v, 小学内容。。。
for(int i = 1; i <= n; i++)
{
b[i] = a[i] / v + b[i-1];//把每一块多走得时间给我加上
}
int q;
cin >> q;
while(q--)//对于每一个询问
{
double t, ans;
cin >> t;
if(b[mid] <= t)
{
printf("-1\n");
return 0;
}//如果所有魔法都使用了但爬上山顶的时间还是小于t的话, 无解, 输出-1
//下面是二分。。。
int l = 0; r = n, ans = 0;
while(l <= r)
{
int mid = (l+r) >> 1;
if(b[mid] > t)//使用前mid个魔法所用的时间超过t的话
{
ans = mid;
r = mid-1;
}
else
{
l = mid + 1;
}
}
printf("%d\n", ans);
}
return 0;
}//完结撒花。。。
呵呵, 其实后面都没有这么详细的代码了。。。
B 荆轲刺秦王
题目描述
咸阳宫的地图可以描述为一个n行m列的矩形。 在这里, 我们规定每一行从左到右为x轴正方向, 每一列中从上到下y轴为正方向,左下角点的坐标为(1,1)。矩形中的点可以分为4种:
1.起点, 也就是荆轲所在点, 在地图中用字符’s’代表。
2.终点, 也就是嬴政所在点, 在地图中用字符’T’代表。
3.卫兵, 再地图中用一个正整数 a i , j a_{i,j} ai,j代表。 在这里,, 一个卫兵 ( i , j ) (i,j) (i,j)可以观察到与他曼哈顿距离小于 a i , j a_{i,j} ai,j的点, 也就是卫兵 ( i , j ) (i,j) (i,j)可以观察到所有满足 ∣x−i∣+∣y−j∣< a i , j ai,j ai,j的点 ( x , y ) (x,y) (x,y)。
4.空地, 在地图中用字符’.'代表,
荆轲的正常移动方式为每秒向八连通的任意方向前进一格。如下图, 中间的点为荆轲当前所在点。每一秒, 他可以走向其余的八个点。
需要注意的是,正常移动时, 荆轲不能踏进任何一个有卫兵或者卫兵能观察到的格子。当然, 他也不能走出咸阳宫, 也就是说, 无论何时, 荆轲的坐标(x,y)都必须满足 1 ≤ x ≤ m 1 \leq x \leq m 1≤x≤m且 1 ≤ y ≤