Cinema Cashier
题面翻译
输入第一行为两个整数 N , K N,K N,K,表示一个大小为 K 2 K^2 K2 的电影院,会来 N N N 波人,相同一波的人必须坐在同一排。
输入第二行有 N N N 个数,表示每波的人数。
定义中心点 ( x c , y c ) , x c = ⌈ k 2 ⌉ , y c = ⌈ k 2 ⌉ (x_c,y_c),x_c=\lceil\frac{k}{2}\rceil,y_c=\lceil\frac{k}{2}\rceil (xc,yc),xc=⌈2k⌉,yc=⌈2k⌉,每个人的花费为 ∣ x − x c ∣ + ∣ y − y c ∣ |x-x_c|+|y-y_c| ∣x−xc∣+∣y−yc∣,要求总花费最少。如果总花费一样,尽量向靠左靠前的位置坐。
如果坐不下,输出 − 1 -1 −1;否则,输出每一波人所在的行以及所在的列的起始和终止位置。
题目描述
All cinema halls in Berland are rectangles with K K K rows of K K K seats each, and K K K is an odd number. Rows and seats are numbered from 1 1 1 to K K K . For safety reasons people, who come to the box office to buy tickets, are not allowed to choose seats themselves. Formerly the choice was made by a cashier, but now this is the responsibility of a special seating program. It was found out that the large majority of Berland’s inhabitants go to the cinema in order to watch a movie, that’s why they want to sit as close to the hall center as possible. Moreover, a company of $ M $ people, who come to watch a movie, want necessarily to occupy $ M $ successive seats in one row. Let’s formulate the algorithm, according to which the program chooses seats and sells tickets. As the request for $ M $ seats comes, the program should determine the row number $ x $ and the segment $ [y_{l},y_{r}] $ of the seats numbers in this row, where $ y_{r}-y_{l}+1=M $ . From all such possible variants as a final result the program should choose the one with the minimum function value of total seats remoteness from the center. Say, — the row and the seat numbers of the most “central” seat. Then the function value of seats remoteness from the hall center is . If the amount of minimum function values is more than one, the program should choose the one that is closer to the screen (i.e. the row number $ x $ is lower). If the variants are still multiple, it should choose the one with the minimum $ y_{l} $ . If you did not get yet, your task is to simulate the work of this program.
输入格式
The first line contains two integers $ N $ and $ K $ ( $ 1<=N<=1000,1<=K<=99 $ ) — the amount of requests and the hall size respectively. The second line contains $ N $ space-separated integers $ M_{i} $ from the range $ [1,K] $ — requests to the program.
输出格式
Output $ N $ lines. In the $ i $ -th line output «-1» (without quotes), if it is impossible to find $ M_{i} $ successive seats in one row, otherwise output three numbers $ x,y_{l},y_{r} $ . Separate the numbers with a space.
样例 #1
样例输入 #1
2 1
1 1
样例输出 #1
1 1 1
-1
样例 #2
样例输入 #2
4 3
1 2 3 1
样例输出 #2
2 2 2
1 1 2
3 1 3
2 1 1
思路(借鉴)
要让下面的式子最小,我们可以尽可能让一批人都挤在一起。
因此我们可以枚举每一批人(就连续的坐在一起),看看什么时候这个值最小,然后记录下来,最终输出。
为什么可以这么想呢?因为我们看这个式子,特别像曼哈顿距离的公式,这样我们转化成几何图形可以知道,分散的点的曼哈顿距离最小肯定是每个点都集合在一起(连续性)。
- 细节1:我们得用st数组来存储位置是否被占用。
- 细节2:题目要求如果有解,则输出三个整数,那么我们在遍历的时候,也应该按照这三个整数的顺序来,就:先遍历行,再遍历列,最后再遍历列的连续范围。当遍历完列的连续范围时,我们就得更新最值。
这道题给我的启示:当数据范围大的时候,我们不妨去想想贪心、模拟的思路来做题目。
代码( O ( n k 3 ) O(nk^3) O(nk3))
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010;
int w[N];
bool st[N][N];
int n,k;
int ans;
int main(){
cin>>n>>k;
//核心坐标
int x=(k+1)/2,y=(k+1)/2;
for(int i=1;i<=n;i++)cin>>w[i];
for(int u=1;u<=n;u++){
int xx=1,yy=1;//答案行,答案列
ans=2e9;
//求最优的位置
for(int i=1;i<=k;i++){//行
for(int j=1;j<=k-w[u]+1;j++){//列
bool f=false;
int t=0;
for(int l=j;l<=j+w[u]-1;l++){//列的范围
if(st[i][l]){
f=true;
break;
}else{
t+=abs(i-x)+abs(l-y);
}
}
if(!f&&ans>t){
ans=t;
xx=i;
yy=j;
}
}
}
//输出最优的
if(ans==2e9)puts("-1");
else{
cout<<xx<<" "<<yy<<" "<<(yy+w[u]-1)<<endl;
for(int i=yy;i<=yy+w[u]-1;i++)st[xx][i]=true;
}
}
return 0;
}