[Swust OJ 781]--牛喝水
The cows have a line of 20 water bowls from which they drink. The bowls can be either right-side-up (properly oriented to serve refreshing cool water) or upside-down (a position which holds no water). They want all 20 water bowls to be right-side-up and thus use their wide snouts to flip bowls.
Their snouts, though, are so wide that they flip not only one bowl but also the bowls on either side of that bowl (a total of three or -- in the case of either end bowl -- two bowls).
Given the initial state of the bowls (1=undrinkable, 0=drinkable -- it even looks like a bowl), what is the minimum number of bowl flips necessary to turn all the bowls right-side-up?
Line 1: A single line with 20 space-separated integers
Line 1: The minimum number of bowl flips necessary to flip all the bowls right-side-up (i.e., to 0). For the inputs given, it will always be possible to find some combination of flips that will manipulate the bowls to 20 0's.
1
|
0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0
|
1
|
3
|
Explanation of the sample:
Flip bowls 4, 9, and 11 to make them all drinkable:
0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 [initial state]
0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 [after flipping bowl 4]
0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 [after flipping bowl 9]
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [after flipping bowl 11]
题目大意:一只牛能把碗翻转过来,(由于嘴太大 ^_^ )同时会把他左右的碗全部翻转,1代表需要翻转的碗,问最少可以几次把碗全部翻转(0表示)
这道题呐,用dfs 也能做 ,以前就是dfs a掉的,今天做了(杭电的Stange Billboard(可以看看))位运算后想了想这不就是一个行为1,列为20的位位运算吗,(上面的说过行大于列就转置,不然第一行枚举2^20,,转置了就只有两种可能了)~~
先上dfs的代码 100ms(反正不低于100)
1 #include<iostream> 2 using namespace std; 3 int bowl[21], step, flag; 4 int range() 5 { 6 int i; 7 for (i = 0; i<20; i++) 8 if (bowl[i] == 1) 9 return 0; 10 return 1; 11 } 12 void turn(int i) 13 { 14 bowl[i] = !bowl[i]; 15 if (i>0) 16 bowl[i - 1] = !bowl[i - 1]; 17 if (i<19)bowl[i + 1] = !bowl[i + 1]; 18 } 19 void DFS(int i, int dp) 20 { 21 if (step == dp) 22 { 23 flag = range(); 24 return; 25 } 26 if (i >= 20 || flag) return; 27 turn(i); 28 DFS(i + 1, dp + 1); 29 turn(i); 30 DFS(i + 1, dp); 31 } 32 int main() 33 { 34 int i; 35 for (i = 0; i < 20; i++) 36 cin >> bowl[i]; 37 for (step = 0; step<20; step++) 38 { 39 flag = 0; 40 DFS(0, 0); 41 if (flag) break; 42 } 43 cout << step << endl; 44 return 0; 45 }
至于用位运算0ms 直接水过~~~
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 #define inf 0x7fffffff 5 #define min(a,b) a<b?a:b 6 int mpt[20], tmp[20], sign[20]; 7 int main(){ 8 int i, j, cnt, minn = inf, x; 9 for (j = 0; j < 20; j++){ 10 cin >> x; 11 if (x) 12 mpt[j] |= 1 << 0; 13 } 14 //行为1,列为20直接转置 15 for (i = 0; i < 1 << 1; i++){ 16 for (j = 0; j < 20; j++) 17 tmp[j] = mpt[j]; 18 for (j = 0; j < 20; j++){ 19 sign[j] = j == 0 ? i : tmp[j - 1]; 20 tmp[j] ^= sign[j]; 21 tmp[j + 1] ^= sign[j]; 22 } 23 if (!tmp[19]){ 24 cnt = 0; 25 for (j = 0; j < 20; j++) 26 if (sign[j] & 1) 27 cnt++; 28 } 29 minn = min(minn, cnt); 30 } 31 cout << minn << endl; 32 return 0; 33 }
关于位运算可以戳戳这里:http://www.cnblogs.com/zyxStar/p/4564335.html