[풀이]백준 풀이(XIV/16988 등)
문제풀이
[Re]Baaaaaaaaaduk2 - Easy(16988)
- 일반 바둑과 다르게 돌을 2개씩 둔다.
- 일반 바둑과 동일하게 자신의 돌로 상대방의 그룹을 빈틈없이 에워싸면 갇힌 돌을 죽일 수 있다. (그룹 내에 빈칸과 인접해 있는 돌이 하나도 없다.)
- 모든 비어있는 칸에 돌을 둘 수 있다.(돌을 두어서 죽어도 상관 없음)
- 일단 그룹화를 시키고나서 시작인 것 같다.
예외1. 둘러쌓였지만 빈 칸이 포함된 경우.. 예외2. 예외1의 상황에서 빈 칸에 돌을 채우면 내가 상대방을 죽일 수도 있다…
결론적으로 현재 판이 주어질 때 바둑돌 2개를 두어 죽일 수 있는 상대 돌의 최대 갯수를 구하자.
ㅎㅎ진짜 쉽넹…
라고 말한 나는 미친사람이었다.
회고
- 삽질1. next_permutation… 그냥 2중포문으로 받으면 된다.
- 삽질2. kCoor로 queue를 만든 것.
- 삽질3. cin을 잘못 받은 것
- 삽질4. calc함수를 생각하지 못했다…
#include <iostream>
#include <vector>
#include <tuple>
#include <queue>
#include <algorithm>
using namespace std;
int n, m, zCnt=0, kCnt =0, Answer=0;
int dx[] = {0, 0, 1, -1};
int dy[] = {1,-1, 0, 0};
int map[21][21];
int mapTemp[21][21];
int visited[21][21];
vector<pair<int,int>> zCoor;
queue<pair<int,int>> kCoor;
vector<pair<int,int>> kCoorTemp;
bool isInside(int a, int b){
if(a>=0 && b>=0 && a<n && b<m) return true;
else return false;
}
void initVisited(){
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
visited[i][j] = false;
}
}
}
void loadMap(){
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
map[i][j] = mapTemp[i][j];
}
}
}
int calc(pair<int,int> m1, pair<int,int> m2){
//m1, m2를 1로 변경하고 돌리는 bfs
int ret = 0;
map[m1.first][m1.second]=1;
map[m2.first][m2.second]=1;
initVisited();
//모든 점 중 필요한 점에서 bfs 다돌린다.
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
//방문했거나 상대방 돌이면 다음꺼 확인
if(visited[i][j] or map[i][j] != 2) continue;
bool isdead = true; // 연결된 돌 중에 빈 칸과 닿아있는게 하나라도 있다면 이 변수를 false로 만들 것이다.
//bfs
queue<pair<int, int> > q;
q.push(make_pair(i,j));
visited[i][j] = true;
int area = 0;
while(!q.empty()){
area++;
pair<int, int> cur = q.front(); q.pop();
for(int i=0; i<4; i++){
int nx = cur.first + dx[i];
int ny = cur.second + dy[i];
//범위를 벗어나지 않아야한다.
if(!isInside(nx,ny)) continue;
//빈 칸이 있으면 안죽어
if(map[nx][ny] == 0) isdead = false;
//방문했거나 상대방 돌이 아니면 pass
if(visited[nx][ny] or map[nx][ny] != 2) continue;
q.push(make_pair(nx,ny));
visited[nx][ny] = true;
}
}
if(isdead) ret += area;
}
}
loadMap();
return ret;
}
int main(){
cin >> n >> m;
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin >> map[i][j];
mapTemp[i][j] = map[i][j];
}
}
zCoor.clear();
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(map[i][j]==0) {
pair<int,int> tmp = make_pair(i,j);
zCoor.push_back(tmp);
zCnt++;
}
}
}
//입력완료
//뻘짓을 했네
for(int i=0; i<zCnt; i++){
for(int j=i; j<zCnt; j++){
if(i!=j){
//1. 맵 변경 완료
pair<int,int> m1 = make_pair(zCoor[i].first, zCoor[i].second);
pair<int,int> m2 = make_pair(zCoor[j].first, zCoor[j].second);
//2 맵 변경 후 bfs시작
Answer = max(Answer,calc(m1,m2));
}
}
}
cout << Answer;
}
[RE]Count Circle Groups(10216)
- 2차원평면위 N곳에 적군의 진영이 있다.
- 진영마다 통신탑이 하나씩 있다.
- i번째 적군의 통신탑은 설치위치로부터 Ri 이내거리에 포함되는 모든지역을 자신의 통신영역 Ai로 가지게 된다.
- 통신영역 Ai와 Aj에서 겹치는 부분이 있다면 진영 i와 j는 직접 통신이 가능하다.
-
꼭 직접 통신이 되지않더라도 몇 다리 건너서라도 통신이 가능하면 i와 j는 통신이 가능한 것으로 본다.
-
서로 통신이 가능한 그룹의 개수를 출력하자.
- 거리니까 원형의 거리를 출력해야하네..
틀린 답
아래 코드도 예쁘게 나오긴한다.. 반례를 못 찾아서 PASS..
;
#include <iostream>
#include <vector>
#include <tuple>
#include <queue>
#include <algorithm>
using namespace std;
int t, n, m, Answer=0;
int rMax = 0, xMax= 0, yMax = 0, group;
int map[5000][5000];
bool visited[5000][5000];
int dx[] = {0, 0, 1, -1};
int dy[] = {1,-1, 0, 0};
//tuple<x,y,r>
vector<tuple<int,int,int>> coor;
queue<pair<int,int>> q;
bool isInside(int a, int b){
if(a>=0 && b>=0 && a<=5000 && b<=5000) return true;
else return false;
}
void initMap(){
for(int i=0; i<5000; i++){
for(int j=0; j<5000; j++){
map[i][j] = 0;
visited[i][j] = false;
}
}
}
bool isCommunicated(int cx, int cy, int nx, int ny, int r){
int x = abs(nx-cx);
int y = abs(ny-cy);
if((r*r) >= (x*x)+(y*y)) {
return true;
}
else {
return false;
}
}
void makeMap(tuple<int,int,int>enemy){
int x, y, r;
tie(x,y,r) = enemy;
//최대 거리가 r이니까 가로든 세로든 r보다 더갈필요는 없음
//모든 점에 대해서 적기지에서 r보다 가까운 곳은 1로 변경!
for(int nx=0; nx<=x+r; nx++){
for(int ny=0; ny<=y+r; ny++){
if(isCommunicated(x,y,nx,ny,r)) map[nx][ny]=1;
}
}
}
void printMap(){
for(int i=0; i<=xMax+rMax; i++){
for(int j=0; j<=yMax+rMax; j++){
cout << map[i][j] << " ";
}
cout << endl;
}
}
void bfs(int sx, int sy, int group){
queue<pair<int,int>> nq;
nq.push(make_pair(sx,sy));
visited[sx][sy] = true;
while(!nq.empty()){
int cx, cy;
pair<int,int> tmp = nq.front();
nq.pop();
tie(cx,cy) = tmp;
map[cx][cy] = group;
for(int i=0; i<4; i++){
int nx = cx + dx[i];
int ny = cy + dy[i];
//범위 밖이면 빠이 (0~5000)
if(!isInside(nx,ny)) continue;
//방문했으면 빠이
if(visited[nx][ny]) continue;
if(map[nx][ny]==1){
nq.push(make_pair(nx,ny));
visited[nx][ny] = true;
map[nx][ny] = group;
}
}
}
}
int main(){
cin >> t;
bool zCheck = false;
for(int i=0; i<t; i++){
cin >> n;
initMap();
group = 1;
for(int i=0; i<n; i++){
int x, y, z;
cin >> x >> y >> z;
tuple<int,int,int> tmp(x,y,z);
coor.push_back(tmp);
q.push(make_pair(x,y));
//맵을 만들자.
rMax = max(rMax,z);
xMax = max(xMax,x);
yMax = max(yMax,y);
makeMap(tmp);
}
if(rMax==0) zCheck=true;
while(!q.empty() && !zCheck){
pair<int,int> tmp = q.front();
q.pop();
if(!visited[tmp.first][tmp.second]){
group++;
bfs(tmp.first, tmp.second, group);
}
}
printMap();
if(zCheck) {
cout << 0;
return 0;
}
cout << group-1 << endl;
//시간/메모리 줄일 수 있을듯
}
}
정답
블로그를 참조했다.
- 중심이(A1,B1)이고 반지름은 r1인 원 A
- 중심이(A2,B2)이고 반지름은 r2인 원 B
겹치는 것 확인 = (A-C)^2 + (B-D)^2 <= (R1+R2)^2 임을 확인하면 된다…
따라서 각각의 진영정보를 토대로 서로 겹치는지만 확인하면 아주 쉽게 끝난다.
#define getDist(x0,y0,x1,y1) ((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1))
#define dbl(r) (r*r)
#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int testcases;
int N; int
enemy[3001][3];
bool isVisit[3001];
int enemyNum;
int adj[3001][3001];
int adjSize[3001];
int main()
{
cin >> testcases;
while (testcases--) {
enemyNum = 0;
cin >> N;
for (int i = 0; i < N; i++) {
for (int j = 0; j < 3; j++) {
cin >> enemy[i][j];
}
isVisit[i] = false;
adjSize[i] = 0;
for (int j = 0; j < N; j++) {
adj[i][j] = -1;
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (i == j) continue;
int dist = getDist(enemy[i][0], enemy[i][1], enemy[j][0], enemy[j][1]);
int bound = dbl((enemy[i][2] + enemy[j][2]));
if (dist <= bound ){
adj[i][adjSize[i]] = j;
adj[j][adjSize[j]] = i;
adjSize[i]++; adjSize[j]++;
}
}
}
for (int i = 0; i < N; i++) {
if (!isVisit[i]) {
enemyNum++;
queue<int> bfs;
bfs.push(i);
while (!bfs.empty()) {
int now = bfs.front();
bfs.pop();
for (int iter = 0; iter < adjSize[now]; iter++) {
int next = adj[now][iter];
if (!isVisit[next]) {
bfs.push(next);
isVisit[next] = true;
}
}
}
}
}
cout << enemyNum << endl;
}
return 0;
}
댓글남기기