1. 程式人生 > >51Nod - 1521 一維戰艦

51Nod - 1521 一維戰艦

一行 喜歡 con output 相互 pre 距離 邊界 class

51Nod - 1521 一維戰艦

愛麗絲和鮑博喜歡玩一維戰艦的遊戲。他們在一行有n個方格的紙上玩這個遊戲(也就是1×n的表格)。

在遊戲開始的時候,愛麗絲放k個戰艦在這個表格中,並不把具體位置告訴鮑博。每一只戰艦的形狀是 1×a 的長方形(也就是說,戰艦會占據a個連續的方格)。這些戰艦不能相互重疊,也不能相接觸。

然後鮑博會做一系列的點名。當他點到某個格子的時候,愛麗絲會告訴他那個格子是否被某只戰艦占據。如果是,就說hit,否則就說miss。

但是這兒有一個問題!愛麗絲喜歡撒謊。他每次都會告訴鮑博miss。

請你幫助鮑博證明愛麗絲撒謊了,請找出哪一步之後愛麗絲肯定撒謊了。

Input
單組測試數據。
第一行有三個整數n,k和a(1≤n,k,a≤2*10^5),表示表格的大小,戰艦的數目,還有戰艦的大小。輸入的n,k,a保證是能夠在1×n的表格中放入k只大小為a的戰艦,並且他們之間不重疊也不接觸。
第二行是一個整數m(1≤m≤n),表示鮑博的點名次數。
第三行有m個不同的整數x1,x2,...,xm,xi是鮑博第i次點名的格子編號。格子從左到右按照1到n編號。
Output
輸出一個整數,表示最早一次能夠證明愛麗絲一定撒謊的點名編號。如果不能證明,輸出-1。點名的編號依次從1到m編號。
Input示例
樣例1
11 3 3
5
4 8 6 1 11

樣例2
5 1 3
2
1 5
Output示例
樣例輸出1
3

樣例輸出2
-1

題解:

    前幾天看到題目實在是沒有思路,然後網絡搜了下,現在回頭在做。

    1, 在一段距離能放戰艦的數量是: (r - l)/(a + 1); 其中 r l 是開邊界。

    2, 那麽中間被一個元素隔開,兩端孤立的距離段則是: (r - mid)/(a + 1), (mid - l)/(a + 1)

    所以,按照上面的思路,可以進行計算。

#include <iostream>  
#include <cstdlib> 
#include <cstring> 
#include <cstdio> 
using namespace std; 
const int MAXN = 200000 + 5; 

int vis[MAXN], x[MAXN]; 

int main(){
	int n, k, a, m, l, r, cur, ans; 
	while(scanf("%d %d %d", &n, &k, &a) != EOF){
		scanf("%d", &m); 
		for(int i=0; i<m; ++i){
			scanf("%d", &x[i]); 
		}
		memset(vis, 0, sizeof(vis)); 
		ans = -1; 
		cur = (n + 1)/(a+1);  
		for(int i=0; i<m; ++i){
			vis[ x[i] ] = 1; 
			l = x[i]-1; r = x[i]+1;  
			while(l >=1 && vis[l] == 0){
				l--; 
			} 
			while(r <= n && vis[r] == 0){
				r++; 
			}
			cur -= (r-l)/(a+1) - (r-x[i])/(a+1) - (x[i]-l)/(a+1); 
			if(cur < k){
				ans = i + 1; 
				break; 
			}
		}
		printf("%d\n", ans );
	}
	return 0; 
}

  

51Nod - 1521 一維戰艦