• bzoj1704/poj3276[Usaco2007 Mar]Face The Right Way自动转身机


    题目链接:bzojpoj

    题目大意:

    有N(1≤N≤5000)只牛站成一排,有些朝前站着.有些朝后站着.农夫约翰需要让所有的牛都朝前站着.幸运的是约翰最近买了一个自动转身机.这个神奇的机器能使K(1≤K≤N)只连续的牛转身. 因为约翰从来都不改变K的价值,请帮助他求出K,使旋转次数M达到最小.同时要求出对应的M.如果不够K只牛的话,转身机是不能工作的。


    题解:

    额写的穷举题

    一开始看这道题:怎么可能才两星啊???啊好难啊随便YY了想一下做法肯定超时啊。然后想想想!打了个感觉很玄学的剪枝还是TLE,继续想优化,终于!我我我我想到了一个O(n^2)的做法了!真高兴OvO。。好吧虽然左←边的神犇们应该都能一眼秒了qwq。

    额说正解(为什么最近碎碎念多了那么多呢

    首先先把牛什么的弄成01串,0是朝后的,1是朝前的,目标就是把串变成全1串。翻转一次就是那一段数都异或1。

    然后枚举K值。对于一个K值,我们再把串从左到右扫一遍求M,为什么可以扫一遍就求到M了呢。

    因为我们要知道,扫到某一位的时候如果之前的翻转操作并不能让现在这一位变成1的话,那就一定要以这一位开始使用一次机器,只有这样才能使这位的零变成1(因为后面的操作都不能影响这一位了啊)。【哦,可能要说下对于以某一头牛开始的翻转操作最多翻一次,翻两次的话就抵消效果了。

    所以每次维护一个 翻转操作对串的影响 的数组就好了,↑这样求到的M一定是对枚举的K来说最小的(没有多余的操作啊)。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define maxn 5010
    
    int sum[maxn],a[maxn];//sum[]就是维护的那个数组
    int main()
    {
    	//freopen("cowturn.in","r",stdin);
    	//freopen("cowturn.out","w",stdout);
    	int n,i,j,k,cnt;char c;
    	scanf("%d",&n);
    	for (i=1;i<=n;i++)
    	{
    		scanf("
    %c",&c);
    		if (c=='B') a[i]=0;
    		else a[i]=1;
    	}
    	for (i=n;i>=1;i--)//K要越大越好所以从后往前枚举
    	{
    		cnt=0;bool bo=true;
    		for (j=1;j<=n;j++) sum[j]=0;
    		for (j=1;j<=n;j++)
    		 if (a[j]^sum[j-1]^sum[j]) sum[j]^=sum[j-1];//之前操作的影响向后传递
    		 else {
    			 if (j+i-1<=n) cnt++;//如果还能翻就累加次数
    		 	 else {bo=false;break;}
    			 sum[j]=sum[j]^sum[j-1]^1;sum[j+i]^=1;//原理同+1-1什么的啊
    			 //就是把[j,j+i-1]这段区间都异或1,到j+i的时候再异或一下就抵消了
    		}
    		if (bo) break;
    	}
    	printf("%d %d
    ",i,cnt);
    	return 0;
    }


  • 相关阅读:
    redis 资料
    php 安装redis php扩展
    Unity生命周期
    疫情下的大学生人格发展研究
    对联一句——百花深处
    Unity实现byte[]合成图像
    Unity实现精灵资源动态加载
    数据结构与算法初步
    Unity中激活子物体
    C#实现自定义列表
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527824.html
Copyright © 2020-2023  润新知