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 }