【51nod-1521】一維戰艦
阿新 • • 發佈:2018-07-22
不能 編號 格子 每次 .html ray 長方形 http main
愛麗絲和鮑博喜歡玩一維戰艦的遊戲。他們在一行有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編號。
開始想的是每加入一個點名編號就重新統計可以放的戰艦數,實際上只需要重新計算這個編號的左右區間就可以了。很容易想到的是用set二分查找,另外set不像vector有排序的概念,所以lower_bound(st.begin(),st.end(),x)是錯誤的,正確的是st.lower_bound(x)。。。我才發現stdio.h比cstdio快了不少(之前好多卡超時的題都A惹QAQ#include <stdio.h> #include <set> #include <iostream> using namespace std; const int N = 1005; set<int>S; int main() { int n, k, a, m, x, ans = -1; bool f = 0; cin>>n>>k>>a>>m; S.insert(n+1); S.insert(0); int c = (n+1)/(a+1);//目前一共可放艦數 for(int i=1; i<=m; i++) { scanf("%d", &x); S.insert(x); //未找到撒謊編號進入 if(!f) { set<int>::iterator it = S.lower_bound(x); set<int>::iterator it1 = it; it1--;//前一個點名編號 set<int>::iterator it3 = it; it3++;//後一個點名編號 int num = (*it3 - *it1)/(a+1);//前後編號之間可以放的戰艦數 c -= num; c += (*it-*it1)/(a+1)+(*it3-*it)/(a+1);//加入該點名編後後總共可放的戰艦數 if(c < k) { ans = i; f = 1; } } } printf("%d\n", ans); return 0; }
還有一種方法不用set也可以解決。從這個編號向左右尋找最近的兩個編號。
#include <stdio.h> using namespace std; const int N = 200005; int mp[N]; int main() { int n, k, a, m, x, ans = -1; bool f = 0; scanf("%d%d%d%d", &n, &k, &a, &m); mp[0] = 1, mp[n+1] = 1; int c = (n+1)/(a+1);//目前一共可放艦數 for(int i=1; i<=m; i++) { scanf("%d", &x); mp[x] = 1; if(!f) { int j, l; for(j=x-1; j>=0&&!mp[j]; j--); for(l=x+1; l<=n&&!mp[l]; l++); int num = (l - j)/(a+1); c -= num; c += (x-j)/(a+1)+(l-x)/(a+1); if(c < k) { ans = i; f = 1; } } } printf("%d\n", ans); return 0; }
【51nod-1521】一維戰艦