Initially want to greedy, similar to the sense of heuristic search ... Later I thought it was impossible, and it was hard to write.
It's better to enumerate. Can be 0 to 2^w in the binary form of each number in the corresponding, the first row each position whether as the center point into the cross lattice.
When 0 is not placed, 1 indicates put.
Why is it possible to enumerate only the first line in all cases?
Since the first line of the case is determined, we can infer that the second line of some states, and then according to the first line must be filled, you can determine the second row of all must be placed in the cross-block position.
After the number of States is generated, the put function is called, and the next line is first affected by the result to determine the next row. (The basis of this algorithm is to fill each row with the last line.)
So when the last line is processed, the legitimacy of the last line can be judged.
Because there are many locations to handle ... Do not want to engage in a lot of binary things, with a bool array to save the state.
#include <iostream>#include<algorithm>using namespacestd;Const intINF =9999999;BOOLmap[ -][ -]={0};BOOLcur[ -][ -]={0};inth,w;voidprint () {cout<<"--------"<<Endl; for(inti =0; i < H; ++i) { for(intj=0; J < W; ++j) {cout<<Cur[i][j]; } cout<<Endl; } cout<<"--------"<<Endl;}voidCopymap () { for(inti =0; i < H; ++i) for(intj=0; J < W; ++j) Cur[i][j]=map[i][j];}voidinit () {cin>>H>>v; for(inti =0; i < H; ++i) { for(intj =0; J < W; ++j) { intl; CIN>>l; MAP[I][J]= l%2;//An even number of 0 odd is 1 } }}//calculate how many 1 in the binary of KintGetones (intk) { intAns =0; while(k>0){ if((k&1))//If the rightmost side is 1ans++; K= k>>1;//throw out the right one at a time; } returnans;}voidPutintLineId,intState ) { //enumeration When we think of a state number 0 for each position in the states that does not put 1 means to put that to fill for(inti =0; i < W; ++i)//from the No. 0 position in the first row to W-1 { if(state& (1<<i)) {//if it is put, fill it out on both sides and below. if(lineid>=1)//you don't have to write .cur[lineid-1][i] =!cur[lineid-1][i]; Cur[lineid][i]= !Cur[lineid][i]; if(i>=1) Cur[lineid][i-1] =!cur[lineid][i-1]; Cur[lineid][i+1] =!cur[lineid][i+1]; Cur[lineid+1][i] =!cur[lineid+1][i]; } }}intbuild () {BOOLhave =false; intres =INF; //First, you enumerate all the possible scenarios for the first row of cross-crosses//then according to the position of the first row can determine the second row of placement, in order to decide the third row .... for(inti =0; I < (1<<W); ++i)//There's a total of 2^w. { //Copy before each enumeration cannot be modified directly on the mapCopymap (); intCNT = Getones (i);//record the number of crosses to be placedPut0, i); //print (); //The first platoon is done, and we're going to determine where each row must be crossed in the first row. for(intK =1; K < H; ++k) {intCurstate =0;//the number of build states is used to call the Put function for(intj =0; J < W; ++j) {if(cur[k-1][J])//if this place on the previous line is 1, which is an odd number, it must be filled at the center of this line.Curstate + = (1<<j); } CNT+=Getones (curstate); Put (k,curstate); } //When you're done, check that the last line is filled, and if it is, all of them are filled with even numbers. BOOLOK =true; for(intj =0; J < W; ++j) {if(cur[h-1][j]) {OK=false; Break; } } if(OK) { the=true; Res=min (res,cnt); } } if(!Have ) Res= -1; returnRes;}intMainintargcChar Const*argv[]) {init (); cout<<build () <<Endl; return 0;}
"Algorithmic Learning note" 74. Enumeration State compression fill scheme SJTU OJ 1391 Smooth toothpick bag (change)