From e6d06fcd037aa59c8305f8b04daf329196c2afe4 Mon Sep 17 00:00:00 2001 From: Konano Date: Thu, 13 Feb 2020 20:30:38 +0800 Subject: [PATCH] refactor HCF --- README.md | 7 +- src/HCF/choose.cpp | 722 +++++++++++++++++++++++---------------------- 2 files changed, 376 insertions(+), 353 deletions(-) diff --git a/README.md b/README.md index 66ad537..72f176b 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,9 @@ make install ## Refactoring…… - [x] BAF -- [ ] HCF +- [x] HCF - [ ] HCF-MoreKeys - [ ] HCF-RESWUEV1 - [ ] HCF-SingleWork - [x] MultField -- [ ] TriField - -- [ ] Need modify wiki -- [ ] Compile +- [ ] TriField \ No newline at end of file diff --git a/src/HCF/choose.cpp b/src/HCF/choose.cpp index 5f8a6bd..455502f 100644 --- a/src/HCF/choose.cpp +++ b/src/HCF/choose.cpp @@ -5,464 +5,490 @@ #pragma warning(disable : 4996) #endif -#include #include -#include -#include +#include #include -#include #include -#include -#include +#include +#include #include -#define rep(i, l, r) for(int i=l; i<=r; i++) -#define dow(i, l, r) for(int i=l; i>=r; i--) -#define clr(x, c) memset(x, c, sizeof(x)) -#define pi acos(-1) -#define travel(i) for(PortalLevelList *p=PlistFirst[i]; p; p=p->next) // 遍历第 i 个 List - using namespace std; -#define maxTotal 1000 -#define maxs 166167001 +#define pi acos(-1) +#define maxPortal 1000 +#define maxField 166167001 -struct Portal // 定义 Portal 结构体,x0,y0 是经纬度坐标,x,y,z 是三维坐标(半径为 1 的球面上),guid,latlng,label 是 JSON 信息 -{ - double x0, y0, x, y, z; - string guid, latlng, label; -} P[maxTotal+1], tmpP[2]; // P[] 储存 Portal 信息,tmpP[] 是记录临时三维向量 +char tmp_char; -bool cmpXY(Portal a, Portal b){return a.x0next) +struct List{int x; List *next;} pl[maxPortal], *pl_head[9], *pl_end = pl; -int n; -// n 为 Portal 数量 +struct xyz { + int x, y, z; + xyz() {} + xyz(int x, int y, int z) : x(x), y(y), z(z) {} + bool operator < (const xyz &a) const { return x < a.x || (x == a.x && y < a.y) || (x == a.x && y == a.y && z < a.z); } + xyz operator + (const xyz &a) const { return xyz(x + a.x, y + a.y, z + a.z); } + xyz operator - (const xyz &a) const { return xyz(x - a.x, y - a.y, z - a.z); } + xyz operator / (const double a) const { return xyz(x / a, y / a, z / a); } +}; -int Field_ID[maxTotal+1][maxTotal+1]; -// Field_ID 是为了方便计算每个 Field 所对应的编号(详细见 GetFL 函数) - -inline void SWAP(int &a, int &b, int &c) +struct Portal { - if (a>b) swap(a,b); - if (b>c) swap(b,c); - if (a>b) swap(a,b); -} -// 将三个数从小到大排序 + double lat, lng, x, y, z, S; + string guid, latlng, label; + xyz pos; + Portal() : pos(0,0,0) {} + Portal(double x, double y, double z) : x(x), y(y), z(z), pos(0,0,0) {} + void to_xyz() { + istringstream iss(latlng); + iss >> lat >> tmp_char >> lng; + x = cos(lat / 180.0 * pi) * cos(lng / 180.0 * pi); + y = sin(lat / 180.0 * pi) * cos(lng / 180.0 * pi); + z = sin(lng / 180.0 * pi); + } + bool operator == (const Portal &a) const { return guid == a.guid; } + bool operator < (const Portal &a) const { return lat < a.lat || (lat == a.lat && lng < a.lng); } +} P[maxPortal]; + +struct Field { + int x; + double S; + Field() {} + Field(int x, double S) : x(x), S(S) {} + bool operator < (const Field &a) const { return S < a.S; } +} qL[maxPortal], qR[maxPortal]; -inline int GetFL(int a, int b, int c) {SWAP(a,b,c); return Field_ID[a][b]+c;} -// 给三个 Portal 的编号求其对应的 Field 的编号 +// Field_ID 是为了方便计算每个 Field 所对应的编号(详细见 GetFL 函数) +int fieldID[maxPortal+1][maxPortal+1]; -inline void GetPortal(int FieldLabel, int &a, int &b, int &c) -{ - a=1; while (a b) swap(a, b); + if (b > c) swap(b, c); + if (a > b) swap(a, b); } -// 给 Field 的编号求其对应的三个 Portal 的编号 - - - - - - -inline void Spin(int lb, int a, int b) -{ - double x=(P[a].y*P[b].z-P[a].z*P[b].y); - double y=(P[a].z*P[b].x-P[a].x*P[b].z); - double z=(P[a].x*P[b].y-P[a].y*P[b].x); - tmpP[lb].x=(P[b].y*z-P[b].z*y); - tmpP[lb].y=(P[b].z*x-P[b].x*z); - tmpP[lb].z=(P[b].x*y-P[b].y*x); +inline int portal2field(int a, int b, int c) { swap3(a, b, c); return fieldID[a][b] + c; } +inline void field2portal(int f_id, int &a, int &b, int &c) { + a = 0; + while (a+1 < num-2 && fieldID[a+1][a+2] + a + 3 <= f_id) a++; + b = a + 1; + while (b+1 < num-1 && fieldID[a][b+1] + b + 2 <= f_id) b++; + c = f_id - fieldID[a][b]; } - -inline double COS() -{ - return (tmpP[0].x*tmpP[1].x+tmpP[0].y*tmpP[1].y+tmpP[0].z*tmpP[1].z) - / sqrt(tmpP[0].x*tmpP[0].x+tmpP[0].y*tmpP[0].y+tmpP[0].z*tmpP[0].z) - / sqrt(tmpP[1].x*tmpP[1].x+tmpP[1].y*tmpP[1].y+tmpP[1].z*tmpP[1].z); + +inline Portal spin(const Portal &a, const Portal &b) { + return Portal( + (b.y * (a.x * b.y - a.y * b.x) - b.z * (a.z * b.x - a.x * b.z)), + (b.z * (a.y * b.z - a.z * b.y) - b.x * (a.x * b.y - a.y * b.x)), + (b.x * (a.z * b.x - a.x * b.z) - b.y * (a.y * b.z - a.z * b.y)) + ); } -inline double Angle(int a, int b, int c) {Spin(0,a,b); Spin(1,c,b); return acos(COS());} -// 计算 a-b-c 在球面上的角度 - -inline double Area(int a, int b, int c) {return Angle(a,b,c)+Angle(b,c,a)+Angle(c,a,b)-pi;} -// 计算 a-b-c 形成的 Field 的大小 - -inline void FXL(int a, int b) -{ - tmpP[0].x=P[a].y*P[b].z-P[a].z*P[b].y; - tmpP[0].y=P[a].z*P[b].x-P[a].x*P[b].z; - tmpP[0].z=P[a].x*P[b].y-P[a].y*P[b].x; +inline double _cos(const Portal &a, const Portal &b) { + return (a.x * b.x + a.y * b.y + a.z * b.z) + / sqrt(a.x * a.x + a.y * a.y + a.z * a.z) + / sqrt(b.x * b.x + b.y * b.y + b.z * b.z); } -inline double COS(int a){return P[a].x*tmpP[0].x+P[a].y*tmpP[0].y+P[a].z*tmpP[0].z;} - -inline bool Left(int a, int b, int c) {FXL(a,b); return COS(c)>0;} -// 判断 c 是否在 a→b 左侧 +inline double angle(const Portal &a, const Portal &b, const Portal &c) { + return acos(_cos(spin(a, b), spin(c, b))); +} -inline bool inField(int a, int b, int c, int d) -{ - if (d==a || d==b || d==c) return false; - if (!Left(a,b,c)) swap(b,c); - return Left(a,b,d) && Left(b,c,d) && Left(c,a,d); +inline double area(const Portal &a, const Portal &b, const Portal &c) { + return angle(a,b,c) + angle(b,c,a) + angle(c,a,b) - pi; } -// 判断 d 是否在 a-b-c 形成的 Field 内 -inline void ChangetoPosition(int a) +inline Portal normal(const Portal &a, const Portal &b) { - istringstream iss(P[a].latlng); - char tmp; - iss >> P[a].x0 >> tmp >> P[a].y0; - P[a].x=cos(P[a].x0/180.0*pi)*cos(P[a].y0/180.0*pi); - P[a].y=sin(P[a].x0/180.0*pi)*cos(P[a].y0/180.0*pi); - P[a].z=sin(P[a].y0/180.0*pi); + return Portal( + a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x + ); } -// 把经纬度坐标转成三维坐标 +inline double dot(const Portal &a, const Portal &b) { return a.x * b.x + a.y * b.y + a.z * b.z;} +inline bool isLeft(const Portal &a, const Portal &b, const Portal &c) { return dot(c, normal(a, b))>0;} -inline void ReadInput(const char *localFileName) // 读入 JSON +inline bool inField(const Portal &a, const Portal &b, const Portal &c, const Portal &d) { - string str, chunk; - - if (localFileName) - { - ifstream fin(localFileName); - if (fin) - while (getline(fin, chunk) && chunk != "") - str += chunk; - else - while (getline(cin, chunk) && chunk != "") - str += chunk; - } + if (d == a || d == b || d == c) return false; + if (!isLeft(a, b, c)) + return isLeft(a, c, d) && isLeft(c, b, d) && isLeft(b, a, d); else - while (getline(cin, chunk) && chunk != "") str += chunk; - - Json::Reader reader; - Json::Value input; - reader.parse(str, input); - - Json::Value::Members arrayMember = input["portals"]["idOthers"]["bkmrk"].getMemberNames(); - for(Json::Value::Members::iterator iter = arrayMember.begin(); iter != arrayMember.end(); ++iter) - { - n++; - P[n].guid = input["portals"]["idOthers"]["bkmrk"][*iter]["guid"].asString(); - P[n].latlng = input["portals"]["idOthers"]["bkmrk"][*iter]["latlng"].asString(); - P[n].label = input["portals"]["idOthers"]["bkmrk"][*iter]["label"].asString(); - ChangetoPosition(n); // 把经纬度坐标转成三维坐标 - } + return isLeft(a, b, d) && isLeft(b, c, d) && isLeft(c, a, d); } +inline void import(const char *localFileName) { + string str, chunk; + try { + ifstream fin(localFileName); + if (fin) { + while (getline(fin, chunk) && chunk != "") str += chunk; + } else throw ""; + } catch (...) { + puts("Please copy bookmarks into here:"); + while (getline(cin, chunk) && chunk != "") str += chunk; + } + Json::Reader reader; + Json::Value input; + Json::Value::Members arrayMember; + reader.parse(str, input); + num = input["portals"]["idOthers"]["bkmrk"].getMemberNames().size(); + printf("Portal nums: %d\n", num); -inline int min3(int a, int b, int c){return (a<=b&&a<=c)?a:(b<=c?b:c);} -inline int min(int a, int b){return a=b&&a>=c)?a:(b>=c?b:c);} - -inline void Max(int &a, int b){if (b>a) a=b;} - -char Level[maxs]; // 记录每个 Field 的最大层数 -short int NextPortal[maxs]; // 记录每个 Field 在达到最大层数时的内点 -int Count[9]; // Count[i] 表示有多少个 Field 其最大层数为 i -int Lmx[maxTotal+1][maxTotal+1]; // Lmx[a][b] 表示向量 a→b 左边所形成的 Field 的最大层数 - - - - - - -clock_t gap; // 记录时间 + if (num > maxPortal) { + printf("Only support no more than %d portals.\n", maxPortal); + getchar(); + exit(0); + } -Json::Value bm, dt, ini_bm, null_dt; // JSON 信息载体 + num = 0; + arrayMember = input["portals"]["idOthers"]["bkmrk"].getMemberNames(); + for(Json::Value::Members::iterator iter = arrayMember.begin(); iter != arrayMember.end(); ++iter) { + P[num].guid = input["portals"]["idOthers"]["bkmrk"][*iter]["guid"].asString(); + P[num].latlng = input["portals"]["idOthers"]["bkmrk"][*iter]["latlng"].asString(); + P[num].label = input["portals"]["idOthers"]["bkmrk"][*iter]["label"].asString(); + P[num].to_xyz(); + num += 1; + } +} +char layer[maxField]; // 记录每个 Field 的最大层数 +short int nextPortal[maxField]; // 记录每个 Field 在达到最大层数时的内点 +int layerCount[8]; // layerCount[i] 表示有多少个 Field 其最大层数为 i +int mxLayer[maxPortal+1][maxPortal+1]; // mxLayer[a][b] 表示向量 a→b 左边所形成的 Field 的最大层数 +clock_t gap; // 记录时间 +int needLayer; // 询问层数 +Json::Value bookmarks, drawnitems, bookmarks_INIT, drawnitems_NULL; +int dr_num = 0; -int QLevel; // 询问层数 +map l2p; // 编号映射到 xyz 参数 +map p2l; // xyz 参数映射到编号 -struct xyz{int x,y,z;} pos[maxTotal+1]; // xyz 是一个自设的参数 -bool operator < (xyz a, xyz b){return a.x M0; // 编号映射到 xyz 参数 -map M1; // xyz 参数映射到编号 +inline void getLabel() { -inline xyz Ave(xyz a, xyz b, xyz c){return (xyz){(a.x+b.x+c.x)/3, (a.y+b.y+c.y)/3, (a.z+b.z+c.z)/3};} -// 由 Field 上三点的 xyz 得到内点的 xyz + // 设置三个顶点的 xyz 参数 + l2p["A1"] = xyz(5e8, 0, 0); + l2p["A2"] = xyz(0, 5e8, 0); + l2p["A3"] = xyz(0, 0, 5e8); + p2l[xyz(5e8, 0, 0)] = "A1"; + p2l[xyz(0, 5e8, 0)] = "A2"; + p2l[xyz(0, 0, 5e8)] = "A3"; -inline void GetOpinion() -{ - M0["A1"]=(xyz){(int)5e8,0,0}, M0["A2"]=(xyz){0,(int)5e8,0}, M0["A3"]=(xyz){0,0,(int)5e8}; // 设置三个顶点的 xyz 参数 - M1[(xyz){(int)5e8,0,0}]="A1", M1[(xyz){0,(int)5e8,0}]="A2", M1[(xyz){0,0,(int)5e8}]="A3"; - - string tmp1="A", tmp2="Lv 0"; - rep(i, 1, QLevel) - { - tmp1[0]='A'+i-1, tmp2[3]='0'+i; - ini_bm["portals"][tmp1]["label"]=tmp2; - ini_bm["portals"][tmp1]["state"]=0; + string str1 = "A", str2 = "Lv 0"; + for (int i = 1; i <= needLayer; i++) { + str1[0] = 'A' + i-1; + str2[3] = '0' + i; + bookmarks_INIT["portals"][str1]["label"] = str2; + bookmarks_INIT["portals"][str1]["state"] = 0; } - ini_bm["portals"]["A"]["bkmrk"]["A1"]["guid"]=""; - ini_bm["portals"]["A"]["bkmrk"]["A2"]["guid"]=""; - ini_bm["portals"]["A"]["bkmrk"]["A3"]["guid"]=""; + bookmarks_INIT["portals"]["A"]["bkmrk"]["A1"]["guid"] = ""; + bookmarks_INIT["portals"]["A"]["bkmrk"]["A2"]["guid"] = ""; + bookmarks_INIT["portals"]["A"]["bkmrk"]["A3"]["guid"] = ""; // LABEL 每一行有四个字符串,“A B C D” 表示以编号为 A,B,C 形成的 Field 的内点的编号为 D - ifstream fin("../LABEL"); - int tmp, num=0; fin >> tmp; for(int i=1, a=1; i> maxLayer; + for(int i = 1, j = 1; i < maxLayer; i++, j *= 3) f_num += j; string a, b, c, d; - rep(i, 1, num) - { + for (int i = 1; i <= f_num; i++) { fin >> a >> b >> c >> d; - M0[a]=Ave(M0[b],M0[c],M0[d]), M1[M0[a]]=a; - if (a[0]-'A'+1<=QLevel) tmp1[0]=a[0], ini_bm["portals"][tmp1]["bkmrk"][a]["guid"]=""; + l2p[a] = (l2p[b] + l2p[c] + l2p[d]) / 3; + p2l[l2p[a]] = a; + if (a[0] - 'A' + 1 <= needLayer) { + str1[0] = a[0]; + bookmarks_INIT["portals"][str1]["bkmrk"][a]["guid"] = ""; + } } } - - - - - - - -int OPtot; // JSON 内 Line 的数量 - -inline string D_toString(double a) -{ - char buffer[20]; - sprintf(buffer, "%f", a); - return buffer; -} - -inline string I_toString(int a) +inline void addPortal(const Portal &a, const int level) { - char buffer[20]; - sprintf(buffer, "%d", a); - return buffer; + string groupName = "A"; + groupName[0] += level - 1; + bookmarks["portals"][groupName]["bkmrk"][p2l[a.pos]]["guid"] = a.guid; + bookmarks["portals"][groupName]["bkmrk"][p2l[a.pos]]["latlng"] = a.latlng; + bookmarks["portals"][groupName]["bkmrk"][p2l[a.pos]]["label"] = a.label; } -inline void AddLine(int a, int b, int lv) +inline void addLink(const Portal &a, const Portal &b, const int level) { - if (lv == 1) dt[OPtot]["color"] = "#0000ff"; - if (lv == 2) dt[OPtot]["color"] = "#2222ff"; - if (lv == 3) dt[OPtot]["color"] = "#4444ff"; - if (lv == 4) dt[OPtot]["color"] = "#6666ff"; - if (lv == 5) dt[OPtot]["color"] = "#8888ff"; - if (lv == 6) dt[OPtot]["color"] = "#aaaaff"; - if (lv == 7) dt[OPtot]["color"] = "#ccccff"; - - dt[OPtot]["latLngs"][0]["lat"] = D_toString(P[a].x0); - dt[OPtot]["latLngs"][0]["lng"] = D_toString(P[a].y0); - dt[OPtot]["latLngs"][1]["lat"] = D_toString(P[b].x0); - dt[OPtot]["latLngs"][1]["lng"] = D_toString(P[b].y0); - - dt[OPtot]["type"] = "polyline"; - - OPtot++; -} + switch (level) { + case 1: drawnitems[dr_num]["color"] = "#0000ff"; break; + case 2: drawnitems[dr_num]["color"] = "#2222ff"; break; + case 3: drawnitems[dr_num]["color"] = "#4444ff"; break; + case 4: drawnitems[dr_num]["color"] = "#6666ff"; break; + case 5: drawnitems[dr_num]["color"] = "#8888ff"; break; + case 6: drawnitems[dr_num]["color"] = "#aaaaff"; break; + case 7: drawnitems[dr_num]["color"] = "#ccccff"; break; + } -inline void AddPortal(int a, int lv) -{ - string tmp="A"; tmp[0]+=lv-1; - bm["portals"][tmp]["bkmrk"][M1[pos[a]]]["guid"] = P[a].guid; - bm["portals"][tmp]["bkmrk"][M1[pos[a]]]["latlng"] = P[a].latlng; - bm["portals"][tmp]["bkmrk"][M1[pos[a]]]["label"] = P[a].label; + drawnitems[dr_num]["latLngs"][0]["lat"] = to_string(a.lat); + drawnitems[dr_num]["latLngs"][0]["lng"] = to_string(a.lng); + drawnitems[dr_num]["latLngs"][1]["lat"] = to_string(b.lat); + drawnitems[dr_num]["latLngs"][1]["lng"] = to_string(b.lng); + drawnitems[dr_num]["type"] = "polyline"; + dr_num++; } -void OutputPlan(int a, int b, int c, int lv) -{ - if (lv == QLevel) return; - SWAP(a,b,c); - if (lv == 1) - { - AddLine(a,b,lv), AddLine(b,c,lv), AddLine(c,a,lv); - pos[a]=(xyz){(int)5e8,0,0}, AddPortal(a,lv); // 由 xyz 参数查询到当前点所对应的编号 - pos[b]=(xyz){0,(int)5e8,0}, AddPortal(b,lv); - pos[c]=(xyz){0,0,(int)5e8}, AddPortal(c,lv); +void outputSolution(int a, int b, int c, int level) { + if (level == needLayer) return; + swap3(a, b, c); + if (level == 1) { + addLink(P[a], P[b], level); + addLink(P[b], P[c], level); + addLink(P[c], P[a], level); + P[a].pos = xyz(5e8, 0, 0), addPortal(P[a], level); // 由 xyz 参数查询到当前点所对应的编号 + P[b].pos = xyz(0, 5e8, 0), addPortal(P[b], level); + P[c].pos = xyz(0, 0, 5e8), addPortal(P[c], level); } - int x=GetFL(a,b,c), d=NextPortal[x]; pos[d]=Ave(pos[a],pos[b],pos[c]); - AddPortal(d,++lv); - AddLine(a,d,lv), AddLine(b,d,lv), AddLine(c,d,lv); - OutputPlan(a,b,d,lv); // 递归输出方案 - OutputPlan(b,c,d,lv); - OutputPlan(c,a,d,lv); + int x = portal2field(a, b, c); + int d = nextPortal[x]; + P[d].pos = (P[a].pos + P[b].pos + P[c].pos) / 3; + addPortal(P[d], ++level); + addLink(P[a], P[d], level); + addLink(P[b], P[d], level); + addLink(P[c], P[d], level); + + // 递归输出方案 + outputSolution(a, b, d, level); + outputSolution(b, c, d, level); + outputSolution(c, a, d, level); } -inline void OutputPlan(int FieldLabel) // 输出方案到 JSON -{ - int a, b, c; GetPortal(FieldLabel,a,b,c); - dt=null_dt; bm=ini_bm; OPtot=0; OutputPlan(a,b,c,1); +// 输出方案到 JSON +inline void outputSolution(int f_id) { + int a, b, c; + field2portal(f_id, a, b, c); + drawnitems = drawnitems_NULL; + bookmarks = bookmarks_INIT; + dr_num = 0; + outputSolution(a, b, c, 1); Json::FastWriter writer; - puts("Bookmarks JSON:"); cout << writer.write(bm) << endl; - puts("DrawTools JSON:"); cout << writer.write(dt) << endl; + puts("Bookmarks JSON:"); cout << writer.write(bookmarks) << endl; + puts("DrawTools JSON:"); cout << writer.write(drawnitems) << endl; } +#define maxRandomChoose 1000000 +int rChoose[maxRandomChoose]; +#define minFieldChoose 10 +#define maxFieldChoose 10 +#define ranFieldChoose 30 - - - - - - - - - -#define OPRandomSize 1000000 -int OPRandom[OPRandomSize]; -#define minField 10 -#define maxField 10 -#define ranField 30 - -inline void OutputResult() -{ +inline void outputResult() { freopen("result.txt", "w", stdout); - priority_queueq; int sz=0, tot=0, FieldLabel; + priority_queue q; + int q_tot, r_tot, f_id; - // 输出最小的前 minField 个方案 - rep(i, 1, n) rep(j, i+1, n) rep(k, j+1, n) if (Level[FieldLabel=GetFL(i,j,k)]>=QLevel) - { - if (sz==minField) q.pop(), sz--; - q.push((Field){FieldLabel,Area(i,j,k)}), sz++; - if (tot<=OPRandomSize) OPRandom[tot++]=FieldLabel; + // 输出最小的前 minFieldChoose 个方案 + q_tot = 0, r_tot = 0; + for (int i = 0; i < num; i++) for (int j = i+1; j < num; j++) for (int k = j+1; k < num; k++) { + if (layer[f_id = portal2field(i, j, k)] >= needLayer) { + if (q_tot == minFieldChoose) { + q.pop(), q_tot--; + } + q.push(Field(f_id, area(P[i], P[j], P[k]))); q_tot++; + + if (r_tot < maxRandomChoose) rChoose[r_tot++] = f_id; + } + } + while (q_tot) { + printf("minimum area: #%d\n\n", q_tot); + outputSolution(q.top().x); + q.pop(); q_tot--; } - dow(i, sz, 1) printf("面积最小:#%d\n\n", i), OutputPlan(q.top().x), q.pop(); - - sz=0, tot=0; - // 输出最大的前 maxField 个方案 - rep(i, 1, n) rep(j, i+1, n) rep(k, j+1, n) if (Level[FieldLabel=GetFL(i,j,k)]>=QLevel) - { - if (sz==maxField) q.pop(), sz--; - q.push((Field){FieldLabel,-Area(i,j,k)}), sz++; + // 输出最大的前 maxFieldChoose 个方案 + q_tot = 0, r_tot = 0; + for (int i = 0; i < num; i++) for (int j = i+1; j < num; j++) for (int k = j+1; k < num; k++) { + if (layer[f_id = portal2field(i, j, k)] >= needLayer) { + if (q_tot == minFieldChoose) { + q.pop(), q_tot--; + } + q.push(Field(f_id, -area(P[i], P[j], P[k]))); q_tot++; + + if (r_tot < maxRandomChoose) rChoose[r_tot++] = f_id; + } + } + while (q_tot) { + printf("maximum area: #%d\n\n", q_tot); + outputSolution(q.top().x); + q.pop(); q_tot--; } - dow(i, sz, 1) printf("面积最大:#%d\n\n", i), OutputPlan(q.top().x), q.pop(); - // 随机输出 ranField 个方案 - random_shuffle(OPRandom, OPRandom+tot); - rep(i, 1, min(tot,ranField)) printf("Random #%d\n\n", i), OutputPlan(OPRandom[i-1]); + // 随机输出 ranFieldChoose 个方案 + random_shuffle(rChoose, rChoose + r_tot); + for (int i = 0; i < min(r_tot, ranFieldChoose); i++) { + printf("random op: #%d\n\n", i+1); + outputSolution(rChoose[i]); + } // 重名预警 - printf("需要注意的重名 Po:\n"); - rep(i, 1, n) rep(j, i+1, n) if (P[i].label == P[j].label) {cout << P[i].label << endl; break;} + printf("duplication of Portal name:\n"); + for (int i = 0; i < num; i++) for (int j = i+1; j < num; j++) if (P[i].label == P[j].label) { + cout << P[i].label << endl; + break; + } fclose(stdout); } +int main() { + srand(time(NULL)); - - - - - - - - - - -int main() -{ cout << "请将导出的 Bookmark 储存为 portal.txt 并放置于同目录下" << endl; getchar(); + import("portal.txt"); - ReadInput("portal.txt"); srand(time(NULL)); + // 按经纬坐标排序 + sort(P, P + num); - cout << "总点数:" << n << endl; - cout << "倒数第二个 Portal:" << P[n-1].label << endl; - cout << "若与读入数据不吻合,则请检查下是否操作有误(或者是触发了尚未修复的 Portal 名称 Bug)" << endl; - getchar(); - - if (n>maxTotal) - { - cout << "Portal 数量超过了 " << maxTotal << " 的上限,请删减。" << endl; - getchar(); return 0; + // 枚举左端点和中间端点,f_tot 记录 Field 总数,fieldID 是为了方便计算每个 Field 所对应的编号(详细见 portal2field 函数) + int f_tot = 0; + for (int i = 0; i < num-2; i++) for (int j = i+1; j < num-1; j++) { + f_tot += num-j; + fieldID[i][j] = f_tot - num; } - sort(P+1, P+1+n, cmpXY); // 按经纬坐标排序 + int f_now = 0, totL, totR; // f_now 表示当前已经处理完了多少个 Field + // 从左往右枚举右端点,从右往左枚举左端点 + for (int c = 2; c < num; c++) for (int a = c-2; a >= 0; a--) { + totL = totR = 0; - int tot=0; rep(i, 1, n-2) rep(j, i+1, n-1) tot+=n-j, Field_ID[i][j]=tot-n; - // 枚举左端点和中间端点,tot 记录 Field 总数,Field_ID 是为了方便计算每个 Field 所对应的编号(详细见 GetFL 函数) - - int now=0, totL, totR; // now 表示当前已经处理完了多少个 Field - rep(c, 3, n) dow(a, c-2, 1) // 从左往右枚举右端点,从右往左枚举左端点 - { - totL=totR=0; - rep(b, a+1, c-1) if (Left(a,c,b)) qL[++totL]=(Field){b,Area(a,b,c)}; else qR[++totR]=(Field){b,Area(a,c,b)}; // 枚举中间端点,qL[] 为向量 a→c 左边的 Portal(总数为 totL),qR[] 为向量 a→c 右边的 Portal(总数为 totR) - if (totL) - { - sort(qL+1, qL+1+totL); // 按面积从小到大排序 - clr(PlistFirst,0); PlistEnd=Plist; // List 初始化 - rep(i, 1, totL) - { - int b=qL[i].x, FieldLabel=GetFL(a,b,c), mxLevel=max(Lmx[c][b],Lmx[b][a]); // mxLevel 是由向量 c→b 和 b→a 左边所形成的 Field 的最大层数所决定的 Level 上限 - char &Lv=Level[FieldLabel]; Lv=1; // Lv 为当前 Field 的 Level - dow(o, mxLevel, 1) travel(o) if (Lv>o) break; else if (inField(a,b,c,p->x)) // 从高到低枚举内层 Field 等级并遍历 List - { - int tmp=min3(o,Level[GetFL(a,b,p->x)],Level[GetFL(b,c,p->x)])+1; // 求内点为 p->x 时当前 Field 所能达到的最大层数 - if (tmp>Lv) Lv=tmp, NextPortal[FieldLabel]=p->x; + for (int b = a+1; b <= c-1; b++) { + if (isLeft(P[a], P[c], P[b])) { + qL[totL++] = Field(b, area(P[a], P[b], P[c])); + } else { + qR[totR++] = Field(b, area(P[a], P[c], P[b])); + } + } + + if (totL) { + sort(qL, qL + totL); + memset(pl_head, 0, sizeof(pl_head)); + pl_end = pl; + for (int i = 0; i < totL; i++) { + int b = qL[i].x; + int f_id = portal2field(a, b, c); + // int mxLayer = ; + // char &Lv = layer[f_id]; + layer[f_id] = 1; + + // 从高到低枚举内层 Field 等级并遍历 List + for(int o = max(mxLayer[c][b], mxLayer[b][a]); o >= 1; o--) { + foreach(o) { + if (layer[f_id] > o) break; else if (inField(P[a], P[b], P[c], P[p->x])) { + int tmp = min3(o, layer[portal2field(a, b, p->x)], layer[portal2field(b, c, p->x)]) + 1; + if (tmp > layer[f_id]) { + layer[f_id] = tmp; + nextPortal[f_id] = p->x; + } + } + } } - int tmp=min(Lv,max(Lmx[a][b],Lmx[b][c])); // 判断下当 b 作为内点 a-c 做边的时候最多能多少层 - PlistEnd->x=b, PlistEnd->next=PlistFirst[tmp], PlistFirst[tmp]=PlistEnd++; // 将 b 加入到 List[tmp] + // 判断下当 b 作为内点 a-c 做边的时候最多能多少层 + int tmp = min3((int)layer[f_id], mxLayer[a][b], mxLayer[b][c]); + + // 将 b 加入到 List[tmp] + pl_end->x = b; + pl_end->next = pl_head[tmp]; + pl_head[tmp] = pl_end++; - Max(Lmx[a][c],Lv); Max(Lmx[c][b],Lv); Max(Lmx[b][a],Lv); // 更新 Lmx 数组 + // 更新 Lmx 数组 + if (mxLayer[a][c] < layer[f_id]) mxLayer[a][c] = layer[f_id]; + if (mxLayer[c][b] < layer[f_id]) mxLayer[c][b] = layer[f_id]; + if (mxLayer[b][a] < layer[f_id]) mxLayer[b][a] = layer[f_id]; - Count[(int)Lv]++; now++; - if ((double)(clock()-gap)/CLOCKS_PER_SEC>=0.1) - system("cls"), printf("%.6lf%%\n", 100.0*now/tot), gap=clock(); // 每隔 0.1s 显示一次百分比进度 + layerCount[(int)layer[f_id]]++; + f_now++; + + // 每隔 0.1s 显示一次百分比进度 + if ((double)(clock() - gap) / CLOCKS_PER_SEC >= 0.1) { + printf("%.6lf%%\n", 100.0 * f_now / f_tot); + gap = clock(); + } } } - if (totR) // 注释同上 - { - sort(qR+1, qR+1+totR); - clr(PlistFirst,0); PlistEnd=Plist; - rep(i, 1, totR) - { - int b=qR[i].x, FieldLabel=GetFL(a,b,c), mxLevel=max(Lmx[a][b],Lmx[b][c]); - char &Lv=Level[FieldLabel]; Lv=1; - dow(o, mxLevel, 1) travel(o) if (Lv>o) break; else if (inField(a,b,c,p->x)) - { - int tmp=min3(o,Level[GetFL(a,b,p->x)],Level[GetFL(b,c,p->x)])+1; - if (tmp>Lv) Lv=tmp, NextPortal[FieldLabel]=p->x; + + if (totR) { + sort(qR, qR + totR); + memset(pl_head, 0, sizeof(pl_head)); + pl_end = pl; + for (int i = 0; i < totR; i++) { + int b = qR[i].x; + int f_id = portal2field(a, b, c); + // int mxLayer = ; + // char &Lv = layer[f_id]; + layer[f_id] = 1; + + // 从高到低枚举内层 Field 等级并遍历 List + for(int o = max(mxLayer[a][b], mxLayer[b][c]); o >= 1; o--) { + foreach(o) { + if (layer[f_id] > o) break; else if (inField(P[a], P[b], P[c], P[p->x])) { + int tmp = min3(o, layer[portal2field(a, b, p->x)], layer[portal2field(b, c, p->x)]) + 1; + if (tmp > layer[f_id]) { + layer[f_id] = tmp; + nextPortal[f_id] = p->x; + } + } + } } - int tmp=min3(Lv,Lmx[c][b],Lmx[b][a]); - PlistEnd->x=b, PlistEnd->next=PlistFirst[tmp], PlistFirst[tmp]=PlistEnd++; + // 判断下当 b 作为内点 a-c 做边的时候最多能多少层 + int tmp = min3((int)layer[f_id], mxLayer[c][b], mxLayer[b][a]); + + // 将 b 加入到 List[tmp] + pl_end->x = b; + pl_end->next = pl_head[tmp]; + pl_head[tmp] = pl_end++; - Max(Lmx[a][b],Lv); Max(Lmx[b][c],Lv); Max(Lmx[c][a],Lv); + // 更新 Lmx 数组 + if (mxLayer[a][b] < layer[f_id]) mxLayer[a][b] = layer[f_id]; + if (mxLayer[b][c] < layer[f_id]) mxLayer[b][c] = layer[f_id]; + if (mxLayer[c][a] < layer[f_id]) mxLayer[c][a] = layer[f_id]; - Count[(int)Lv]++; now++; - if ((double)(clock()-gap)/CLOCKS_PER_SEC>=0.1) - system("cls"), printf("%.6lf%%\n", 100.0*now/tot), gap=clock(); + layerCount[(int)layer[f_id]]++; + f_now++; + + // 每隔 0.1s 显示一次百分比进度 + if ((double)(clock() - gap) / CLOCKS_PER_SEC >= 0.1) { + printf("%.6lf%%\n", 100.0 * f_now / f_tot); + gap = clock(); + } } } } - system("cls"); - rep(i, 3, 7) printf("%d 重竹笋解: %d 个\n", i, Count[i]); - puts(""); puts(""); - printf("请问要来份多少重的竹笋?(3-7)\n"); + for (int i = 3; i <= 7; i++) printf("%d Layers: %d Solutions\n", i, layerCount[i]); + needLayer = 0; + while (needLayer < 3 || needLayer > 7) { + puts("What kind of solutions do you need? (3-7)\n"); + scanf("%d", &needLayer); + } - QLevel=3; scanf("%d", &QLevel); - puts("有关信息正在输出到result.txt,祝你好运>.<"); - GetOpinion(); - OutputResult(); - puts("OK"); + puts("Wait for a moment, and then you can see the results in `result.txt`, good luck >.<"); + getLabel(); + outputResult(); return 0; }