描述
http://poj.org/problem?id=3185
20个碗,要全部反转过来.反转某个碗,其相邻的碗(左右两边)也要反转.
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 5538 | Accepted: 2172 |
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?
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.
0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0
3
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]
分析
反转(开关问题).
这一类问题的一个小变形.唯一的不同之处在于在区间边缘可以用长度为2的区间,这就让问题不能裸着做了= =.由于区间只存在转和不转,并且没有先后顺序,所以对于左边的长度为2的区间,只有转/不转两种情况,右同.所以共有2*2=4中情况,于是我们可以分这4种情况,把每一种情况中两个特殊区间的都先处理完,然后剩下的区间就是模板问题了.再来思考右边的那个长度为2的区间,对于转或不转可以在最后进行判断,故只要讨论2种情况即可.
注意点:
1.对于右边的长度为2的区间,如果要转不能忘了res++.
2.这道题n=20,k=3,做起来方便.可以思考任取的n与k.
#include<cstdio>
#include<cstring>
#include<algorithm>
using std :: min; const int maxn=,n=,k=,INF=0x7fffffff;
bool b[maxn],f[maxn];
int ans=INF; void solve(int res)
{
bool sum=false;
memset(f,false,sizeof(f));
for(int i=;i<=n-;i++)
{
if(b[i]^sum)
{
f[i]=true;
sum^=true;
res++;
}
if(i->) sum^=f[i-];
}
bool l2=b[n-]^sum;
sum^=f[n-];
bool l1=b[n]^sum;
if(l2!=l1) return;
if(l2==true) res++;
ans=min(ans,res);
} void init()
{
for(int i=;i<=n;i++)
{
int a;
scanf("%d",&a);
b[i]=a== ? true : false;
}
solve();
b[]=!b[];
b[]=!b[];
solve();
printf("%d\n",ans);
} int main()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
init();
fclose(stdin);
fclose(stdout);
return ;
}