题意
有20只碗,现在要使得它们全部变成碗口朝上的状态,一把下去可能同时反转3个或2个(首尾),求最小翻转次数。
Input
0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0
Output
3
Hint
翻转碗4、9和11:
0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 [初始状态]
0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 [翻转碗4之后]
0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 [翻转碗9之后]
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [翻转碗11之后]
题解
1,反转的先后顺序是不重要的;
2,对一个开关进行2次或2次以上的反转是多余的。
- 如果条件是每次必须反转3个碗的话,那么就很简单,先考虑最左端的碗,如果碗朝下,那么这个碗必须反转,同时带动后面两个碗一起反转。
- 但是条件是在两端可以出现同时只反转两个碗的情况,这时候只要注意判断两端反转两个碗的情况,顺序枚举时,把右端只有两个碗的情况进行处理。倒序枚举一遍,把左端只有两个碗的情况进行处理。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<cmath>
using namespace std;
#define ios ios::sync_with_stdio(false)
int dx[]={-1,0,1,0,0},dy[]={0,1,0,-1,0};
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
typedef pair<double,int> pdi;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=25;
int a[N];
int b[N];
int cnt1,cnt2;
int main()
{
for(int i=0;i<20;i++) cin>>a[i];
for(int i=0;i<20;i++) b[i]=a[i];
for(int i=0;i<20;i++)
{
if(b[i] == 1)
{
if(i == 19)
{
cnt1=20;
break;
}
cnt1++;
b[i]=!a[i],b[i+1]=!b[i+1];
if(i+2 < 20) b[i+2]=!b[i+2];//如果只有两个碗,跳过
}
}
for(int i=0;i<20;i++) b[i]=a[i];
for(int i=19;i>=0;i--)
{
if(b[i] == 1)
{
if(i == 0)
{
cnt2=20;
break;
}
cnt2++;
b[i]=!b[i],b[i-1]=!b[i-1];
if(i-2 >= 0) b[i-2]=!b[i-2];//如果只有两个碗,跳过
}
}
cout<<min(cnt1,cnt2)<<endl;
// system("pause");
}