18709 魔法

时间限制:1000MS  代码长度限制:10KB
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC

Description

农夫约翰的奶牛场有很多奶牛,奶牛有黑白两种颜色。现在奶牛们排成整齐的一列去参加镇上的游行活动。
约翰希望白色奶牛都排在前面,黑色的奶牛都排在后面。但现在队列中奶牛的颜色是混乱的,并且奶牛们都不愿意改变位置。
幸运的是,约翰有一根魔法棒,每挥舞一次魔法棒就可以改变一头奶牛的颜色。
请问,约翰至少要挥舞多少次魔法棒,才能将队列改成他希望的状态。注意,可以将所有的奶牛都变成白色,或者都变成黑色。

输入格式

第一行一个正整数n,表示奶牛的头数。(1<=n<=200000)。
第二行n个正整数,均为1或2,1表示白色奶牛,2表示黑色奶牛。

输出格式

一个正整数,表示挥舞魔法棒的最少次数。

输入样例

7
2 2 1 1 1 2 1

输出样例

3

提示

可以把1和2号奶牛变成1,7号奶牛变成2,或者全部奶牛变成1,最少需要3次。

文章供个人学习用。

思路:

这题模拟出所有情况,然后取最小值就可以了。

有三种情况达成条件:全白,全黑,前白后黑

第一个思路:直接跳到第一个出现黑的地方,把后面的全部变黑,记录变化次数。错误,因为不仅可以白变黑,黑也的可以变白,无法确定在哪一个点开始“前白后黑”,而每个点的情况都是不同的。

所以接下来开始考虑每个点的情况。

第二个思路:是比较每一个下标处,做到“前白后黑”所需要的变化次数,取出最小值。

初见代码(错误!!!)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define min(a,b,c)c<(a<b?a:b)?c:(a<b?a:b) //int a[200000];void input(int* a, int n) {for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);a[i]--;        //while is 0(f),black is 1(t)}
}
int main(){int a[200];int num1 = 0, num2 = 0;int Min=99999;memset(a, -1, 200 * sizeof(int));int n, i = 1;scanf("%d", &n);input(a, n);while (1) {if (n == 1) {printf("%d", 1);return 0;}while (a[i] == a[i+1] && a[i+1] != -1) i++;int j;for (j = 1; j <= n; j++) {if (j <= i && a[j])num1++;if(j > i && !a[j])num1++;if (j <= i && !a[j])num2++;if (j > i && a[j])num2++;}Min = min(Min, num1, num2);num1 = num2 = 0;if (i >= n) break;i++;      }printf("%d",Min);return 0;
}

数据最大到200000,oj提示超时了,检查时发现这段代码把“前黑后白”也算进去了......

要把时间复杂度降到O(n2)以下,那就优化一下吧,用num枚举是不行的了,那就在输入的同时建一个sum[n]储存下黑或白的个数?这样就不用再把数组倒出来数一遍了。

恰巧 a[n]的值的前缀和等于黑的个数(输入时自动减1,白是0,黑是1),可以用sum[i]存下i前的黑个数。

那就建立一个方程,用sum求“前白后黑”的方法数。

ans(答案)要做到 i-1前全白,i后全黑

ans[i]=i-1前黑的个数+i后白的个数

i-1前黑就是sum[i-1],i后白也可以用i前黑求。

i后白=n-i后黑-(i-1)

i后黑=n前黑-(i-1)前黑

化简

ans[i]=2sum[i-1]-(i-1)+n-sum[n]

特例:i=1时,ans[i]=n-sum[n];i=n时,ans[i]=sum[i-1],n=1时直接输出0

a可以直接当ans用

代码(错误!!!但能过oj)

#include <stdio.h>
#include <string.h>
#define min(a,b)a<b?a:b
#define inf (0x3f3f3f)
int a[200100],sum[200100];
void input(int *sum,int* a, int n) {sum[0] = 0;for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);a[i]--;                                         //while is 0(f),black is 1(t)sum[i] = sum[i - 1] + a[i];}
}
int main(){int Min=inf,n,i;memset(a, -1, 200100 * sizeof(int));scanf("%d", &n);input(sum,a,n);a[1] = n - sum[n];if (n == 1) {printf("%d", 0); return 0;}else a[n] = sum[n - 1];for (i = 2; i < n; i++){a[i] = 2 * sum[i - 1] - (i - 1) + n - sum[n];Min = min(Min, a[i]);}printf("%d",min(Min,a[n]));return 0;
}

通过,然后拿到答案


#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n,a[200005],t[200005];
int main()
{ios::sync_with_stdio(0),cin.tie(0);int i,j,ans=200001;cin>>n;for(i=1;i<=n;i++){cin>>a[i];if(a[i]==2)t[i]=t[i-1]+1;elset[i]=t[i-1];}for(i=1;i<=n;i++)ans=min(ans,t[i-1]+n-i-t[n]+t[i]);cout<<ans<<endl;return 0;
}

在求前缀和里,答案更具有一般性。

ans=min(ans,t[i-1]+n-i+t[i]-t[n]),t[i-1]是求i-1前黑的个数,(n-i+t[i]-t[n])是求i后白的个数

t[i]-t[n]是i到n之间的黑的个数,n-i减t[i]-t[n]就是i到n之间白的个数了。

但只有当sum[i]=1才跟我的成立,显然是我的答案错了。大概是测试用例里恰巧最小方法的sum[i]=1,或者同时有一个ans也是1。

反思一下,我在求i后白的时候绕了远路,写代码应该追求简单而且明显看不出错误

SCAU 18709 魔法相关推荐

  1. SCAU18709魔法

    SCAU18709魔法 18709 魔法 时间限制:1000MS 代码长度限制:10KB 提交次数:0 通过次数:0 题型: 编程题 语言: 不限定 Description 农夫约翰的奶牛场有很多奶牛 ...

  2. scau数据结构习题

    18708 最大子段和 时间限制:1000MS 代码长度限制:10KB 提交次数:0 通过次数:0 题型: 编程题 语言: 不限定 Description 一个整数序列,选出其中连续且非空的一段使得这 ...

  3. python常用魔法函数

    1.__init__(): 所有类的超类object,有一个默认包含pass的__init__()实现,这个函数会在对象初始化的时候调用,我们可以选择实现,也可以选择不实现,一般建议是实现的,不实现对 ...

  4. [JS]题解 | #魔法数字#

    题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...

  5. 喵哈哈村的魔法考试 Round #1 (Div.2) 题解源码(A.水+暴力,B.dp+栈)

    A.喵哈哈村的魔法石 发布时间: 2017年2月21日 20:05   最后更新: 2017年2月21日 20:06   时间限制: 1000ms   内存限制: 128M 描述 传说喵哈哈村有三种神 ...

  6. Houdini魔法特效制作学习教程

    大小解压后:12.1G 1920X1080 mp4 语言:英语+中英文字幕 Houdini已经成为特效行业的热门工具. 谁运用它的力量,谁就势不可挡. 魔法咒语.科幻盾牌和电磁脉冲冲击波.掌握特效的艺 ...

  7. 魔法引用函数magic_quotes_gpc和magic_quotes_runtime的区别和用法

    PHP提供两个方便我们引用数据的魔法引用函数magic_quotes_gpc和magic_quotes_runtime, 这两个函数如果在php.ini设置为ON的时候,就会为我们引用的数据碰到单引号 ...

  8. python神秘的魔法函数_Python魔法函数

    1.什么是魔法函数 魔法函数即Python类中以__(双下划线)开头,以__(双下划线)结尾的函数,Python提供的函数,可让咱们随意定义类的特性 示例: class Company(object) ...

  9. 刻意练习:Python基础 -- Task11. 魔法方法

    背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...

最新文章

  1. (转)如何修改maven的默认jdk版本
  2. 点云学习在自动驾驶中的研究概述
  3. 双绞线,同轴电缆和光纤电缆之间的区别—Vecloud微云
  4. .idea文件夹是做什么的_33 个 IDEA 最牛配置,写代码太爽了!
  5. 全数字实时仿真平台SkyEye的同步数据流语言可信编译器的构造
  6. STM32使用DMA接收串口数据
  7. 【中台实践】滴滴大数据研发中台的最佳实践.pdf(附下载链接)
  8. Chrome OS 72.0.3626.117 发布
  9. 2017-01-20_dp测试
  10. linux生成ssh密钥
  11. APP隐私合规检测工具Camille环境搭建
  12. 一个屌丝程序猿的人生(四十二)
  13. 000webhost – 1500M支持PHP可绑米免费虚拟主机
  14. 个性化lightswitch登录屏幕(附源码)
  15. APP后台服务器阿里云Win系统服务器搭建的方法
  16. PHPMyWind支持Word粘贴
  17. 响应式织梦模板工业机械设备类网站
  18. Apache DolphinScheduler 在叽里呱啦的实战经验
  19. oracle成功的原因,【案例】Oracle报错OUI-67076产生原因和MOS官方解决办法
  20. 境内上市和境外上市区别

热门文章

  1. 《和平精英》与永久自行车界合作
  2. java 阿里云服务器流下载慢的可能原因
  3. 实战linux内核精简
  4. java播放swf文件_Java-如何在应用程序中嵌入并执行swf文件?
  5. 时间序列分析之指数平滑法(holt-winters及代码)
  6. vue项目通讯录_Vue实现类似通讯录功能(下)
  7. 细粒度识别 | 百度细粒度识别方案
  8. C语言十进制转八进制
  9. 用Requests下载百度一页图片,以下载芳心纵火犯为例
  10. linux脚本简单定时,shell之定时周期性执行脚本的方法示例