分治法——巨人与鬼问题
生活随笔
收集整理的這篇文章主要介紹了
分治法——巨人与鬼问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:在平面上有n個巨人和n個鬼,沒有三者在同一條直線上。每個巨人需要選擇一個不同的鬼,向其發送質子流消滅它。質子流由巨人發射,沿直線行進,遇到鬼后消失。由于質子流交叉是很危險的,所有質子流經過的線段不能有交點。請設計一種給巨人和鬼配對的方法。
分析:主要就是把圖上的點分成兩份,每份中鬼和巨人一樣多,依次遞歸,并保證不能有交點。
第一步,先找y軸最小的點,其次是x軸最小,按這個點為原點,劃極坐標,從(0,),開始找直到找到相同數量的巨人和鬼停止。
第二步,連接巨人與鬼。剩下再進行分治遞歸。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<algorithm> using namespace std; typedef long long ll;typedef struct node {int id;int x;int y;int type;double angle;bool operator<(const node &t) {return angle < t.angle;} }NODE; NODE p[1000];//結構體數組,用來儲存每個人的信息 int ans[1000];//結構,ans[i]=j代表編號i和編號為j的相連 void sovel(int l, int r);int main() {memset(ans, 0, sizeof(ans));int x, y, t, len = 1;while (scanf("%d%d%d", &t, &x, &y) != EOF)// 錄入數據 {p[len].x = x;p[len].y = y;p[len].id = len;//對應IDif (t == 1)p[len].type = 1;//表示類型elsep[len].type = -1;len++;}len--;sovel(1, len);for (int i = 1; i <= len; i++)printf("%d ", ans[i]);return 0; }void sovel(int l, int r)//遞歸求解,分治思想 {NODE t;if (l >= r) return;int pos = l;//初始化為第一個for (int i = l + 1; i <= r; i++)//找編號l-r區域內左下角節點if (p[i].y < p[pos].y || p[i].y == p[pos].y&&p[i].x < p[pos].x)pos = i;t = p[l];//交換p[l] = p[pos];p[pos] = t;int cnt = p[l].type;//從第一個開始for (int i = l + 1; i <= r; i++)//計算點與左下角點的角度大小p[i].angle = atan2(p[i].y - p[l].y, p[i].x - p[l].x);sort(p+l+1 , p + r+1);//以角度大小排序for (int i = l + 1; i <= r; i++){cnt += p[i].type;if (cnt == 0)//當遍歷過后的區域巨人和鬼的數量相同時{ans[p[l].id] = p[i].id;//鏈接左下角點和當前點ans[p[i].id] = p[l].id;sovel(l + 1, i - 1);//分治,遞歸求解左邊區域sovel(i + 1, r);//分治,遞歸求解右邊區域break;}}return; }?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的分治法——巨人与鬼问题的全部內容,希望文章能夠幫你解決所遇到的問題。