题目网址:http://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1201
有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。
Input
有多个case,每个case输入一行01符号串(长度不超过1000),1表示反面朝上,0表示正面朝上。
Output
对于每组case,如果可以翻,输出最少需要翻动的次数,否则输出NO。
Sample Input
Sample Output
HINT
对于第一组测试数据,无论怎样操作,都无法完成.
对于第二组测试数据,只需反转一次最右面的牌即可
对于第三组测试数据,需要翻转第一张牌和最后一张牌
每一次翻都会影响左右的牌,那么我们肯定是先把前面的牌确定好了,再去决定后面的牌怎么翻,一张牌翻不翻取决于它之前那张牌的状态。考虑第一张翻与不翻的情况,最后去最小值。
代码有点丑。。。。
#include<stdio.h>
#include<string.h>
int main()
{
char s[1010];
int s1[1010],a1[1010];
int i,len,cnt1,cnt2;
while(~scanf("%s",s)){
len=strlen(s),cnt1=1,cnt2=0;
for(i=0;i<len;i++){
if(s[i]=='0') s1[i]=-1;
else s1[i]=1;
a1[i]=s1[i];
}
if(len==1){
if(s1[0]==1) printf("1\n");
else printf("0\n");
continue;
}
s1[0]=-s1[0];
s1[1]=-s1[1];
for(i=1;i<len;i++){
if(s1[i-1]==1){
cnt1++;
s1[i-1]=-1;
s1[i]=-s1[i];
if(i!=len-1) s1[i+1]=-s1[i+1];
}
}
if(s1[len-1]==1) cnt1=-1;
for(i=1;i<len;i++){
if(a1[i-1]==1){
cnt2++;
a1[i-1]=-1;
a1[i]=-a1[i];
if(i!=len-1) a1[i+1]=-a1[i+1];
}
}
if(a1[len-1]==1) cnt2=-1;
if(cnt1==-1&&cnt2==-1) printf("NO\n");
else{
if(cnt1==-1) printf("%d\n",cnt2);
else if(cnt2==-1) printf("%d\n",cnt1);
else printf("%d\n",cnt1>cnt2?cnt2:cnt1);
}
}
return 0;
}
下面是一道加强版的
http://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1623
Description
给你一串01序列,每次翻转连续k长度的序列(0变1,1变0),使所有的字符都变成0,要求翻转最小的次数,如果不存在输出T T.
Input
输入一个01串,
第二行输入一个k
01串长度,k<=100000.
Output
输出最小翻转次数,若不存在则输出T T
Sample Input
Sample Output
每次翻必须是连续的k个字符。用一个数组a【n】表示这个位置多翻了几次,再用一个x变量统计到该位置一共翻了多少次,最后这个位置翻的次数就等于x-a【n】。最后用奇偶性判断该位置要不要翻。(感觉很有技巧。。)
感觉也可以用树状数组做。
AC代码:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <map>
using
namespace
std;
typedef
long
long
ll;
int
main(){
int
a[100010],x,sum,len,y,k,i;
char
s[100010];
while
(~
scanf
(
"%s%d"
,s,&k)){
memset
(a,0,
sizeof
(a));
x=sum=0;
len=
strlen
(s);
for
(i=0;i+k-1<len;i++){
y=x-a[i];
if
((y%2==0&&s[i]==
'1'
)||(y%2==1&&s[i]==
'0'
)){
x++;
sum++;
}a[i+k]=x;
}
for
(;s[i];i++){
y=x-a[i];
if
((y%2==0&&s[i]==
'1'
)||(y%2==1&&s[i]==
'0'
)){
printf
(
"T T\n"
);
goto
out;
}
}
printf
(
"%d\n"
,sum);
out:;
}
return
0;
}