• Face The Right Way 开关(POJ3276)


    描述:
    ( N 头牛排成了一列。每头牛或者向前或者向后。为了让所有的牛都面向前方,农夫约翰买了 一台自动转向的机器。 这个机器在购买时就必须设定一个数值 K,机器每操作一次恰好使 K 头连续的牛转向。 请求出为了让所有的牛都能面向前方需要的最少的操作次数 M 和对应的 最小的 K。 前是'F',后是'B')

    枚举一个K,然后考虑如何求出此时的M.

    一、如果第一头牛需要反转,因为只有1-K这个区间包含它,所以一定要翻转

    二、考虑第二头牛,如果需要翻转那么重复上面的步骤。

    这样的复杂度是(O(n^3))

    每次翻转牛,需要把k头牛都去翻转,这太麻烦了,可以优化掉。

    (f[i])表示以i为起点的区间是否翻转过

    那么如果f[i]=1,它的效果一直持续到f[i+k]就失效了

    所以维护一个sumn变量,表示在i以前k-1头牛翻转过的次数

    那么每次循环,要sumn-=f[i-k+1],因为已经失效

    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,f[5009];//f[i]表示i,i+1,.....i+k-1牛都反转
    char cow[5009];
    int fun(int k)
    {
    	memset(f,0,sizeof(f));
    	int ans=0;//反转次数
    	int sumn=0;
    	for(int i=1;i<=n-k+1;i++)
    	{
    		if(sumn%2==0&&cow[i]=='B')//要反转了 
    			f[i]=1,ans++;
    		else if(sumn%2==1&&cow[i]=='F')//要反转了
    			f[i]=1,ans++;
    		sumn+=f[i];
    		if(i-k+1>=1)	sumn-=f[i-k+1];
    	} 
    	//第n-k+2头牛以后不能反转了,判断是否可行
    	for(int i=n-k+2;i<=n;i++)
    	{
    		if(sumn%2==0&&cow[i]=='B')	return -1;
    		else if(sumn%2==1&&cow[i]=='F')	return -1;
    		sumn+=f[i];
    		if(i-k+1>=1)	sumn-=f[i-k+1];
    	}
    	return ans; 
    } 
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)	cin>>cow[i];
    	int k,ans=999999999;
    	for(int i=1;i<=n;i++)//判断步长i时是否可行 
    	{
    		int x=fun(i);
    		if(x!=-1&&x<ans)
    		k=i,ans=x;
    	}
    	cout<<k<<" "<<ans;
    }
    
  • 相关阅读:
    php 微信-支付宝APP支付(退款)参数获取
    宝塔面板下安装svn版本管理(Centos)
    获取上传文件浏览器路径
    PHP 自制简易其它网站调用密文加密解密
    获取嵌入的资源
    设计模式02(结构性设计模式)
    人为控制随机概率
    设计模式01(创建性设计模式)
    插件式开发
    使用Word2010直接编辑、发布博客→博客园cnblogs
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12605645.html
Copyright © 2020-2023  润新知