1. 程式人生 > >Codeforces1071C Triple Flips 【構造】【Four Russians】

Codeforces1071C Triple Flips 【構造】【Four Russians】

node force ini num flip while triple 利用 lips

題目分析:

這種題目顯然可以先考慮哪些無解。我們發現我們不考慮操作次數的時候,我們可以選擇連續的三個進行異或操作。

這樣我們總能使得一個序列轉化為$000...000xy$的形式。換句話說,對於$000...0001$,$000...0010$,$000...0011$考慮無解條件即可。

這時候寫一個暴力程序,用$O(n^2*2^n)$的算法可以發現其中一個是總長小於$7$無解,另外兩個是小於$8$無解。

然後觀察題目要求的操作次數與$n/3$有關,不難想到每$3$個分成一組,然後在組內調成$0$,允許利用組外信息,每組只允許用一次操作。但這樣操作數會超過($011 or 110$)。

那我們放寬一下限制,每$6$個分成一組,在組內調成$0$,允許利用組外信息,每組只允許操作兩次。這樣就可以了(我一開始以為$110111$是不行的,寫了一個暴力後後來發現我腦殘了)。

這樣我們考慮Four Russians,預處理出來每$6$組怎麽走,最後對剩余的暴力就行了。

代碼:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int maxn = 102000;
  5 
  6 int n,a[maxn],f[1<<12];
  7 struct node{int x,y,z;};
  8 vector <node> des[64];
  9 
 10 void init(){
 11     queue<int> q;
 12     int
N = 6; 13 memset(f,0x3f,sizeof(f)); 14 f[0] = 0; q.push(0); 15 while(!q.empty()){ 16 int k = q.front();q.pop(); 17 for(int i=0;i<N;i++){ 18 if(f[k^(1<<i)] > f[k] + 1){ 19 for(int j=0;j<des[k].size();j++) 20 des[k^(1<<i)].push_back(des[k][j]);
21 des[k^(1<<i)].push_back((node){i,6,12-i}); 22 f[k^(1<<i)] = f[k]+1; 23 q.push(k^(1<<i)); 24 } 25 for(int j=i+1;j<N;j++){ 26 int z = (1<<i)+(1<<j); 27 if(j+(j-i) < N) z |= (1<<2*j-i); 28 if(f[k^z] > f[k]+1){ 29 for(int fr=0;fr<des[k].size();fr++) 30 des[k^z].push_back(des[k][fr]); 31 des[k^z].push_back((node){i,j,2*j-i}); 32 f[k^z] = f[k]+1; 33 q.push(k^z); 34 } 35 } 36 } 37 } 38 } 39 40 node opt[maxn]; 41 int num; 42 43 node lst[maxn]; 44 45 void Remain(){ 46 queue<int> q; 47 memset(f,0x3f,sizeof(f)); 48 //for(int i=0;i<64;i++) des[i].clear(); 49 f[0] = 0;q.push(0); 50 int N = min(n,12); 51 while(!q.empty()){ 52 int k = q.front();q.pop(); 53 for(int i=0;i<N;i++){ 54 for(int j=i+1;j<N;j++){ 55 if(j+(j-i) >= N) break; 56 int z = (1<<i)+(1<<j)+(1<<2*j-i); 57 if(f[k^z] > f[k]+1){ 58 f[k^z] = f[k]+1; 59 lst[k^z] = (node){i,j,2*j-i}; 60 q.push(k^z); 61 } 62 } 63 } 64 } 65 int z = 0; 66 for(int i=n-N+1;i<=n;i++){z = (z<<1)+a[i];} 67 if(f[z] > 1e8){puts("NO");} 68 else{ 69 puts("YES"); 70 printf("%d\n",num+f[z]); 71 for(int i=1;i<=num;i++){ 72 printf("%d %d %d\n",opt[i].x,opt[i].y,opt[i].z); 73 } 74 while(z){ 75 printf("%d %d %d\n",n-lst[z].z,n-lst[z].y,n-lst[z].x); 76 int pp = z; 77 z ^= (1<<lst[pp].x); z ^= (1<<lst[pp].y); z^= (1<<lst[pp].z); 78 } 79 } 80 } 81 82 void work(){ 83 for(int i=1;i<=n;i+=6){ 84 if(i+12 > n) break; 85 int z = (a[i+5]<<5)+(a[i+4]<<4)+(a[i+3]<<3)+(a[i+2]<<2)+(a[i+1]<<1)+a[i]; 86 for(int j=0;j<des[z].size();j++){ 87 opt[++num] = des[z][j]; 88 opt[num].x += i; opt[num].y += i; opt[num].z += i; 89 a[opt[num].x] ^= 1; a[opt[num].y] ^= 1; a[opt[num].z] ^= 1; 90 } 91 } 92 Remain(); 93 } 94 95 int main(){ 96 scanf("%d",&n); 97 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 98 init(); 99 work(); 100 return 0; 101 }

Codeforces1071C Triple Flips 【構造】【Four Russians】