D - 牛吃药 [PSA]
HackerRank - charging-the-batteries
问题描述
半个月之前Alice买了一些竹竿,拼接之后Alice把它截成等长的四段,围出一个正方形的牛棚用来养牛。由于Alice的畜牧经验不足,这头牛患了病。Alice找到当地的兽医开药,并药物拌入饲料喂给这头牛。
假设这个牛棚是个边长为N的正方形,牛棚中所有的点描述为从(0,0)到(N,N)的坐标,牛棚的边缘的各点都堆有饲料,而其中只有M个点放置的是拌有药品的饲料。
假设牛在吃完一堆饲料再吃下一堆时,只会选择与刚吃完这堆相邻近的饲料。现在这头牛需要吃K堆含药饲料才能痊愈,吃每堆饲料要花1分钟。
若从吃完第一堆开始计时,请问这头牛最少要额外花几分钟才能达到吃药的目标
数据输入
第一行有三个整数N,M,K
接下来有M行,每行两个整数表示拌入药物的饲料的坐标,题目保证给出的坐标在正方形的边缘
- 1 ≤ N,M ≤105
- 1 ≤K ≤ M
- 0 ≤ xi,yi≤N
- xi与yi至少有一个为0或为N(保证坐标在正方形牛棚的边缘)
数据输出
输出一行,一个整数,代表牛吃到相应数量的药最短可能花费的时间
样例1
输入样例
5 5 3 5 3 0 0 0 4 3 0 1 5
输出样例
6
提示
输入样例的解如下图示,牛从E开始吃第一堆。吃完E点的第一堆开始计时,第1分钟在点(0,5)吃,第2分钟在点(0,4)吃,…直到第6分钟吃完(0,0)的饲料,吃了3次药达到目标,花费6分钟。当然,如果牛先从B开始然后顺时针吃C和E也可以,同样花费6分钟
这里我是逆时针的,将各坐标按四条边的顺序展开,就像拆盒子,将二维转换成一维。 顺时针同理。
总的点的个数为4*(n+1)-4 注意是能取到N,N的 所以应该是N+1
本来考虑对每个点都要枚举 但研究后发现只需要将有药的点加入LIST然后按大小(一维化后有大小)排序,直接可以很方便的取到位置i和位置i+k-1(要去掉自身的1)之间的距离,方便快捷!在枚举上加了点贪心的思想。
对于遍历LIST可能i+k-1越界的情况,可以通过取余%s.size()来循环,注意当对一个点循环的时候,初始位置的点相当于转了一周了,因此要加上总的点的个数即4*(n+1)-4。
题目因为可以取到0,0和n,n 所以经常在具体+1或者-1的问题上卡一会,需要有足够的逻辑推理能力分析好,或者做的多了就有经验了!
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(),m = sc.nextInt(),k=sc.nextInt();
// int arr[] = new int[4*(n+1)-4];
int x=0,y=0,p=0;
ArrayList<Integer> s = new ArrayList<Integer>();
while(m-- !=0) {
x = sc.nextInt();
y = sc.nextInt();
if(y==0)
p=x;
else if(x==n)
p=n+y;
else if(y==n)
p=2*n+(n-x);
else if(x==0)
p=3*n+(n-y);
s.add(p);
}
Collections.sort(s);
int ans=999999;
int temp,mid;
for (int i = 0; i < s.size(); i++) {
if(i+k-1>=s.size())
mid = s.get((i+k-1)%s.size()) + 4*(n+1)-4;
else
mid = s.get((i+k-1)%s.size());
temp = Math.abs(mid-s.get(i));
if(ans>temp) {
ans = temp;
}
}
System.out.println(ans);
}
}