CodeForces - 200ACinema
| Time Limit: 1500MS |
|
Memory Limit: 262144KB |
|
64bit IO Format: %I64d & %I64u |
Submit Status
Description
The capital of Berland has the only movie theater in the country. Besides, it consists of only one room. The room is divided into n rows, each row consists of m seats.
There are k people lined up to the box office, each person wants to buy exactly one ticket for his own entertainment. Before the box office started selling tickets, each person found the seat that seemed best for him and remembered it as a pair of coordinates (xi,?yi), where xi is the row number, and yi is the seat number in this row.
It is possible that some people have chosen the same place, then when some people see their favorite seat taken in the plan of empty seats in the theater, they choose and buy a ticket to another place. Each of them has the following logic: let‘s assume that he originally wanted to buy a ticket to seat (x1,?y1), then when he comes to the box office, he chooses such empty seat (x2,?y2), which satisfies the following conditions:
- the value of |x1?-?x2|?+?|y1?-?y2| is minimum
- if the choice is not unique, then among the seats that satisfy the first condition, this person selects the one for which the value of x2 is minimum
- if the choice is still not unique, among the seats that satisfy the first and second conditions, this person selects the one for which the value of y2 is minimum
Your task is to find the coordinates of a seat for each person.
Input
The first input line contains three integers n, m, k (1?≤?n,?m?≤?2000, 1?≤?k?≤?min(n·m,?105) — the number of rows in the room, the number of seats in each row and the number of people in the line, correspondingly. Each of the next k lines contains two integers xi, yi (1?≤?xi?≤?n, 1?≤?yi?≤?m) — the coordinates of the seat each person has chosen. Numbers on the same line are separated by a space. The pairs of coordinates are located in the order, in which people stand in the line, starting from the head (the first person in the line who stands in front of the box office) to the tail (the last person in the line).
Output
Print k lines, each containing a pair of integers. Print on the i-th line xi,?yi — the coordinates of the seat, for which the person who stands i-th in the line will buy the ticket.
Sample Input Input
3 4 61 11 11 11 21 31 3 Output
1 11 22 11 31 42 3 Input
4 3 122 22 22 22 22 22 22 22 22 22 22 22 2 Output
2 21 22 12 33 21 11 33 13 34 24 14 3
|x1-x2|+|y1-y2| 大家可以理解為橫著走多少步,豎著走多少步,加起來就是它的值,現在主要思維是,從一個點開始選擇,可能相同的路徑已經進行過一次,為了防止逾時,我們最主要的工作是減少相同路徑重複走幾次,如此通過一個d[x][y]表示這個點周圍已經走了多少次這裡我們要考慮一個情況,就是包圍情況,如果一個點的位置在另一個點選擇的時候就已經訪問了,那麼我們就要通過另一個點更新該點現在講解這份代碼的含義:for(int i=-1; i<=1; i++) { for(int j=-1; j<=1; j++) { if(x+i<=0||y+j<=0||x+i>=n||y+j>=m)continue; d[x][y]=max(d[x][y],d[x+i][y+j]-abs(i)-abs(j)); }}d[x][y]之前已經說明了,代表著從這個點開始周圍的d-1步內都已經被人給選擇,不是空位置那麼對於d[x][y]與d[x+i][y+j],大家可以畫個圖,或者是在腦海裡思考一下
如果d[x+i][y+j]為零的,證明d[x][y]與d[x+i][y+j]是沒有交集如此得到的肯定還是d[x][y]因為d[x+i][y+j]-abs(i)-abs(j),這個代表著(x+i,y+j)這個點到(x,y)的距離,這個式子肯定小於零接著我們思考如果d[x+i][y+j]從(x+i,y+j)這個點開始周圍的d-1步內都已經被人給選擇,且(x,y)這個點也包括在d-1步內,那麼我們可以思考一下,如果這個點已經被訪問了,那麼可不可以通過其他點的d值得到我這個點最小應該走多少步的d值呢,答案是肯定的,因為如果d[x+i][d+j]步內包括有(x,y)這個點被訪問,那麼這個點的d[x+i][y+j]值減去abs(i)+abs(j)的值就是他(x,y)周圍已經訪問了點的最大半徑
如此取所有情況的最大值,這裡i與j的範圍可以自行擬定,因為通過上述說明他的值可以取合格任何值,但是出於時間複雜度的考慮大家可以選擇(-1,1),或者是(-2,2),或者是(-3,3)皆可。
代碼呈上:
/*Author: 2486Memory: 19488 KBTime: 795 MSLanguage: GNU G++ 4.9.2Result: Accepted*/#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int maxn=2000+5;bool vis[maxn][maxn];int d[maxn][maxn];int n,m,k,ex,ey;//這個函數的功能是將d轉換為行列進行檢查,代碼大家都懂bool Check(int x,int y) { int l=max(x-d[x][y],1),r=min(x+d[x][y],n); for(int i=l; i<=r; i++) { int t=d[x][y]-abs(i-x); if(y-t>0&&!vis[i][y-t]) { ex=i; ey=y-t; return false; } if(y+t<=m&&!vis[i][y+t]) { ex=i; ey=y+t; return false; } } return true;}int main() { //freopen("D://imput.txt","r",stdin); int x,y; scanf("%d%d%d",&n,&m,&k); for(int f=0; f<k; f++) { scanf("%d%d",&x,&y); if(!vis[x][y]) { printf("%d %d\n",x,y); vis[x][y]=true; continue; } for(int i=-1; i<=1; i++) { for(int j=-1; j<=1; j++) { if(x+i<=0||y+j<=0||x+i>=n||y+j>=m)continue; d[x][y]=max(d[x][y],d[x+i][y+j]-abs(i)-abs(j)); } } while(Check(x,y)) {//接著一步一步往外擴充 d[x][y]++; } vis[ex][ey]=true; printf("%d %d\n",ex,ey); } return 0;}
|