这是一道.. 怎么说呢 只能用龌龊来形容的题目..
折腾了两天, 重写了两遍, 第一次在题目里用链表, 有点为难自己的意思, 不过确实暂时还没想到其他可以省空间的办法.
思路:
1. 每一块用一个节点存储, 存储方式我用的点阵.. 先随便找出一个点 然后dfs搜出这个点所在的区域
2. 每一块cake正过来反过来各转4个90度, 用从上到下从左到右一个点一个点比过去这样来排序, 有点傻不过还没发掘出什么具有[旋转不变性]的数学方法可以算出方向不同的cake的特征.
3. 选出8个方向(360度/90度*翻转的2面)最大的cake存储
细节:
1. 排序用qsort就很方便
2. 用了个format()把cake仅靠坐标系,这样sort()过后cake之间的比较是数组里元素一一对应的比较
刚刚好250行.. 不是说前两页1009是最恶心的吗..被骗了..
#include <iostream> #include <string.h> #include <stdlib.h> using namespace std; typedef struct coo { int x,y; } Coo; typedef struct cake { Coo a[10000]; int n,amount; struct cake *next; } Cake; int t,n,w,h; Coo a1[10000],a2[10000]; bool cherry[100][100]; Cake *newpiece,*a1cake,*a2cake; int comp(const void *a,const void *b) { int t; if((t=(*(Coo *)a).y-(*(Coo *)b).y)!=0) return -t; return (*(Coo *)a).x-(*(Coo *)b).x; } void dfs_init(Coo *a) { for(int i=0;i<w;i++) for(int j=0;j<h;j++) cherry[i][j]=false; for(int i=0;i<n;i++) cherry[a[i].x][a[i].y]=true; return; } Cake *dfs() { Cake *bake; int m1,m2; bake=(Cake *)malloc(sizeof(Cake)); bake->n=bake->amount=0; for(int i=0;i<w;i++) for(int j=0;j<h;j++) if(cherry[i][j]) { bake->a[0].x=i; bake->a[0].y=j; cherry[i][j]=false; bake->n++; i=w; break; } if(bake->n==0) return NULL; m1=0; m2=1; while(m1!=m2) { for(int i=-1;i<=1;i++) for(int j=-1;j<=1;j++) { if((i+j==1||i+j==-1)&& bake->a[m1].x+i>=0 && bake->a[m1].x+i<w && bake->a[m1].y+j>=0 && bake->a[m1].y+j<h && cherry[bake->a[m1].x+i][bake->a[m1].y+j]) { bake->a[m2].x=bake->a[m1].x+i; bake->a[m2].y=bake->a[m1].y+j; m2++; cherry[bake->a[m1].x+i][bake->a[m1].y+j]=false; } } m1++; } bake->n=m2; return bake; } // This produces a new rotated cake void rotate(Cake *&a) { int x; for(int i=0;i<a->n;i++) { x=a->a[i].x; a->a[i].x=a->a[i].y; a->a[i].y=-x; } return; } void roll(Cake *&a) { for(int i=0;i<a->n;i++) a->a[i].x*=-1; return; } void format(Cake *f) { Coo corner; qsort((void *)(f->a),f->n,sizeof(Coo),comp); corner=f->a[0]; for(int i=1;i<f->n;i++) if(corner.x>f->a[i].x) corner.x=f->a[i].x; for(int i=0;i<f->n;i++) { f->a[i].x-=corner.x; f->a[i].y-=corner.y; } return; } // Cake p1 and p2 should have been sorted. otherwise can't do comparing bool isBigger(Cake *p1,Cake *p2) { int t; for(int i=0;i<p1->n;i++) { t=comp((void *)(p1->a+i),(void *)(p2->a+i)); if(t<0) return true; if(t>0) return false; } return false; } //always sort *newpiece. void sort() { Cake *tbc,*temp; //The Biggest Cake =D tbc=newpiece; format(tbc); temp=(Cake *)malloc(sizeof(Cake)); *temp=*tbc; for (int i=2;i<=8;i++) { if(i==5) roll(temp); else rotate(temp); format(temp); if(isBigger(temp,tbc)) { *tbc=*temp; } } free(temp); newpiece=tbc; } /* isCakeALie: Search matched cake in the list. Input: global variable *a1cake and *newpiece Output: If there is a match, output a pointer to the cake(in the list), otherwise return NULL; */ Cake *isCakeALie() { int i; Cake *p; p=a1cake; while(p) { if(p->n==newpiece->n) { for(i=0;i<p->n;i++) if(p->a[i].x!=newpiece->a[i].x||p->a[i].y!=newpiece->a[i].y) break; if(i==p->n) break; } p=p->next; } return p; } //seal newpiece into a1cake void seal() { Cake *pos; if(pos=isCakeALie()) { pos->amount++; free(newpiece); return; } pos=a1cake; a1cake=newpiece; newpiece->next=pos; a1cake->amount=1; return; } //eat one cake at one time in *a1cake bool fuck() { Cake *pos,*temp; pos=isCakeALie(); free(newpiece); if(pos==NULL) return false; if(pos->amount==1) { if(a1cake==pos) { a1cake=a1cake->next; free(pos); return true; } for(temp=a1cake;temp->next!=pos;temp=temp->next); temp->next=pos->next; free(pos); return true; } pos->amount--; return true; } int main() { bool okay; Cake *temp; cin>>t; while (t--) { cin>>w>>h>>n; for (int i=0;i<n;i++) cin>>a1[i].x>>a1[i].y; for (int i=0;i<n;i++) cin>>a2[i].x>>a2[i].y; a1cake=NULL; dfs_init(a1); while (1) { newpiece=dfs(); if (!newpiece) break; sort(); seal(); } dfs_init(a2); okay=true; while (1) { newpiece=dfs(); if (!newpiece) break; sort(); if (!fuck()) { okay=false; free(newpiece); break; } //free(newpiece); Do it inside fuck() } if (a1cake) okay=false; if (okay) cout<<"YES\n"; else cout<<"NO\n"; while(a1cake) { temp=a1cake; a1cake=a1cake->next; free(temp); } } return 0; }
本来我也以为1009是最恶心的,果断被骗了,
往昔韶华又遭挖坟,长叹~ 🙂