poj3185 开关问题

题意:有20个碗排成一排,有些碗口朝上,有些碗口朝下。每次可以反转连续的3只碗,如果该碗为边界上的碗,则只有一侧的碗被反转。求最少需要反转几次,可以使得所有碗口均朝上。0为上,1为下

 传送门:https://vjudge.net/problem/POJ-3185

这题也是挑战程序设计竞赛来的。看了白书的例题其实这就很好想了。先分别枚举第一个碗翻不翻转,然后依次从左往右枚举给去。例如判断第i个翻不翻转,这时候i-1,i-2已经确定翻不翻转。然而影响i-1的有

i-2,i-1,i,所以为了使i-1向上,i一定可以确定下来翻不翻转。具体看代码吧。

 1 // Cease to struggle and you cease to live
 2 #include <iostream>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <vector>
 9 #include <set>
10 #include <map>
11 #include <stack>
12 using namespace std;
13 typedef long long ll;
14 int a[26];
15 int op[26];
16 void solve(){
17     int ans1=0,ans0=0;
18     op[1]=1;
19     if(a[1]^op[1]) op[2]=1;
20     else op[2]=0;
21     for(int i=3;i<=20;++i){
22         int c=(op[i-1]+op[i-2])%2;
23         if(c^a[i-1]) op[i]=1;
24         else op[i]=0;
25     }
26     int c=(op[20]+op[19])%2;
27     if(c^a[20]) ans1=0x3f3f3f3f;
28     else for(int i=1;i<=20;++i) ans1+=op[i];
29     op[1]=0;
30     if(a[1]^op[1]) op[2]=1;
31     else op[2]=0;
32     for(int i=3;i<=20;++i){
33         int c=(op[i-1]+op[i-2])%2;
34         if(c^a[i-1]) op[i]=1;
35         else op[i]=0;
36     }
37     c=(op[20]+op[19])%2;
38     if(c^a[20]) ans0=0x3f3f3f3f;
39     else for(int i=1;i<=20;++i) ans0+=op[i];
40     printf("%d",min(ans0,ans1));
41 }
42 int main() {
43     for(int i=1;i<=20;++i) scanf("%d",&a[i]);
44     solve();
45     return 0;
46 }
View Code

 

posted @ 2019-05-10 22:34  小布鞋  阅读(260)  评论(0编辑  收藏  举报