【hihocoder1257 2015北京賽區I】【構造 從公式入手】Snake Carpet 構造矩陣使得恰好容納1~n個拐拐蛇行圖案
阿新 • • 發佈:2019-01-29
#include<stdio.h> #include<string.h> #include<map> #include<vector> #include<math.h> #include<algorithm> using namespace std; #define MS(x,y) memset(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) const int dy[2][4]={0,1,0,1, 1,0,-1,0}; const int dx[2][4]={1,0,-1,0, 0,1,0,1}; int n,H,W; const int N=1005; vector<pair<int,int> >a[N]; int b[N][N]; void push(int w,int y,int x) { a[w].push_back(MP(y,x)); b[y][x]=w; } void listfill(int y,int x,int w1,int w2) { int size1=w1; int size2=w2; int d=0; while(size1--) { push(w1,y,x); y+=dy[0][d]; x+=dx[0][d]; d=(d+1)%4; } while(size2--) { push(w2,y,x); y+=dy[0][d]; x+=dx[0][d]; d=(d+1)%4; } } void linefill(int y,int x,int w1,int w2) { int size1=w1; int size2=w2; int d=0; while(size1--) { push(w1,y,x); y+=dy[1][d]; x+=dx[1][d]; d=(d+1)%4; } while(size2--) { push(w2,y,x); y+=dy[1][d]; x+=dx[1][d]; d=(d+1)%4; } } //用所以奇數畫正方形 void square(int y,int x,int top) { for(int o=top;o>=1;o-=2) { ++y; ++x; int d=o/2; int yy=y+d; int xx=x+d; for(int i=yy;i>=y;i--)push(o,i,x); for(int i=x+1;i<=xx;i++)push(o,y,i); } } //用所有偶數畫矩形 void rectangle(int h,int w,int top) { if(h&1) { int u=top; int v=h+h-u; int x=1; while(u>v) { listfill(1,x,u,v); u-=2; v+=2; x+=2; } } else { int u=top; int v=w+w-u; int y=1; while(u>v) { linefill(y,1,u,v); u-=2; v+=2; y+=2; } } } void odd() { H=(n+1)/2; W=n; int mv=n; int h=H; int w=W-(mv+1)/2; square(0,w,mv); rectangle(h,w,n-1); } void even() { H=n/2; W=n+1; int mv=n-1; int h=H; int w=W-(mv+1)/2; square(0,w,mv); rectangle(h,w,n); } void printmap() { for(int i=1;i<=H;i++) { for(int j=1;j<=W;j++)printf("%d ",b[i][j]); puts(""); } } void print() { printf("%d %d\n",H,W); for(int i=1;i<=n;i++) { for(int j=0;j<i;j++)printf("%d %d ",a[i][j].first,a[i][j].second); puts(""); } //printmap(); } int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++)a[i].clear(); if(n&1)odd(); else even(); print(); } return 0; } /* 【trick&&吐槽】 比賽的時候不要太悠閒了,不給自己的壓力很多時候造成的惡果是,悲慘地只恰好差一分鐘AC TwT 【題意】 給你一個n([1,500]),表示有n條蛇,蛇的身長從1到n,每條蛇所佔的格子數也恰好等於其身長。 我們希望把這n條蛇,不交叉不溢位地都放到一個h*w的矩形中。(也就是說h*w=(1+n)*n/2) 並且使得: 對於身長為奇數的蛇(1除外),其扭曲的次數恰好為奇數; 對於身長為偶數的蛇(2除外),其扭曲的次數恰好為偶數。 讓你構造出其方案,並按照身長從1~n,依次輸出所有蛇。對於每條蛇,從頭到尾輸出其u偶在位置。 【型別】 構造 【分析】 首先,我們要分析這個矩形的形狀,矩形的形狀是h*w的話,h和w必定是其面積和的因子。 於是我每次想要枚舉出最小的滿足這個要求的h,然後再進行構造,然後就踏上了悲慘之路。 一個比較優秀的姿勢是什麼呢? 就是——既然h*w=(1+n)*n/2,我們就從這個公式入手! 所以,如果n為奇數,那我們就有因子{(1+n)/2和n}; 如果n為偶數,那我們就有因子{n/2和(1+n)}。 然後,我們觀察到,不論n為奇數還是偶數,對於所有的奇數,我們都是可以這麼安排的—— 1357 3357 5557 7777 我們發現,當n為奇數時,所有的奇數,恰好可以構成一個(n+1)/2的正方形 當n為偶數時,所有的奇數,恰好可以構成一個(n-1+1)/2=n/2的正方形 於是,我們可以剔除這個正方形。 然後,對於n為奇數,目前的矩形就是(n+1)/2 * (n-1)/2 對於n為偶數,目前的矩形就是n/2 * (n+2)/2 然後我們此時剩下的全部都是偶數 對於n%4==1,(n+1)/2 * (n-1)/2 可以用(n-1,2),(n-3,4)這樣湊,形成的對數恰好是(n-1)/4對,每對的和恰好是n+1 對於n%4==2,n/2 * (n+2)/2 可以用(n)(n-2,2),(n-4,4)這樣湊,形成的對數恰好是(n+2)/4對,每對的和恰好是n 對於n%4==3,(n+1)/2 * (n-1)/2 可以用(n-1)(n-3,2),(n-5,4)這樣湊,形成的對數恰好是(n+1)/4對,每對的和恰好是n-1 對於n%4==0,n/2 * (n+2)/2 可以用(n,2)(n-2,4),(n-4,6)這樣湊,形成的對數恰好是n/4對,每對的和恰好是(n+2) 而()中的每個數或每一對,能拐就拐,於是就都很容易就在2*d的格子中構造出解。於是就可以AC啦。 這個可以分開寫,也可以歸納寫,總之我們就可以這樣AC啦~啦啦啦啦~ 【時間複雜度&&優化】 O((n+1)*n/2) */