poj 3276 反转开关问题(一) DP+模拟
2014-03-04 00:40
357 查看
题意:n头牛,F表示朝前,B表示朝后,每次可以让连续的k头牛变换方向,要使所有的牛都朝前,求最小的转向次数及此时的k
Sample Input7 B B F B F B B
Sample Output
3 3
穷举肯定是要超时的 2^n个状态...但是先思考一些规律吧:
1、转动奇数次,必然与初始方向相反;
2、转动偶数次,必然与初始方向相同;
枚举k:1-n,得到O(n^3)的代码:(这个代码会超时,只是模拟而已)
//TLE O(n^3)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 5005
int s[MAXN];
int n;
int test(int k)
{
int i,j,ans=0;
for(i=0;i<n-k+1;i++)
{
if(!s[i])
{
for(j=i;j<i+k;j++)
{
s[j]=!s[j];
}
ans++;
}
}
for(j=i;j<n;j++)
if(!s[j])
return -1;
return ans;
}
int main()
{
int i,len,kmin,m,mmin,k;
char cow[MAXN];
while(scanf("%d",&n)!=EOF)
{
memset(s,0,sizeof(s));
mmin = MAXN;
m=-1;
for(i=0;i<n;i++)
{
scanf("%c",&cow[i]);
if(cow[i]=='\n')
i--;
}
cow[i]='\0';
for(k=1;k<=n;k++)
{
for(i=0;i<n;i++)
{
if(cow[i] == 'F')
s[i]=1;
else
s[i]=0;
}
m=test(k);
///////////////
//printf("m=%d\n",m);
///////////////
if(m>=0&&m<mmin)
{
kmin=k;
mmin=m;
}
}
printf("%d %d\n",kmin,mmin);
}
return 0;
}
再做处理是可以降低时间复杂度的
f[i] 表示从i-k+1到i头牛的反转情况,值为1表示反转,值为0表示没有反转
那么sum=f[i-k+1]+f[i-k+2]+...+f[i-1],如果sum为基数,那么转动奇数次,必然与初始方向相反,如果sum为偶数,必然与初始方向相同。
于是省去一重循环,得到O(n^2)的代码 AC
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 5005
int s[MAXN];
int f[MAXN];
int n;
int test(int k)
{
int i,j,ans=0,sum=0;
memset(f,0,sizeof(f));
for(i=0;i<n-k+1;i++)
{
if((sum)%2 == 1)
{
if(s[i])
{
ans++;
f[i]=1;
}
}
else
{
if(!s[i])
{
ans++;
f[i]=1;
}
}
sum+=f[i];
if(i-k+1>=0)
sum-=f[i-k+1];
}
for(i=n-k+1;i<n;i++)
{
if(sum%2)
{
if(s[i])
return -1;
}
else
{
if(!s[i])
return -1;
}
if(i-k+1>=0)
sum-=f[i-k+1];
}
//if(!s[i])
// return -1;
return ans;
}
int main()
{
int i,len,kmin,m,mmin,k;
char cow[MAXN];
while(scanf("%d",&n)!=EOF)
{
memset(s,0,sizeof(s));
mmin = MAXN;
m=-1;
for(i=0;i<n;i++)
{
scanf("%c",&cow[i]);
if(cow[i]=='\n')
{
i--;
continue;
}
if(cow[i] == 'F')
s[i]=1;
else
s[i]=0;
}
cow[i]='\0';
for(k=1;k<=n;k++)
{
m=test(k);
if(m>=0&&m<mmin)
{
kmin=k;
mmin=m;
}
}
printf("%d %d\n",kmin,mmin);
}
return 0;
}
相关文章推荐
- POJ 3276 反转(开关问题)
- POJ3276—Face The Right Way 【常用技巧—反转(开关问题)】
- poj 3276 Face The Right Way 反转(开关问题)
- Face The Right Way POJ - 3276 简单开关问题
- POJ 3276 Face The Right Way(开关问题)
- POJ_3276_Face The Right Way_区间反转问题
- 【POJ 3276 Face The Right Way】+ 尺取法 + 开关问题
- POJ3276——开关问题
- poj3276 Face The Right Way 反转问题
- POJ 3276 Face The Right Way (开关问题的优化_好题)
- POJ 3276 Face The Right Way【开关问题】
- POJ - 3276 Face The Right Way(开关问题)
- poj 3276 开关反转
- POJ 3276 —— 开关问题
- POJ 3276 Face The Right Way 反转(开关问题)
- POJ 3276-Face The Right Way(牛面向前方-开关问题)
- POJ 3276 Face The Right Way 开关问题
- 150_反转(开关问题) Face the right way (POJ No.3276)
- poj 3276 Face The Right Way【开关问题】
- POJ 3276 (一维开关问题)