题面:

传送门

题目描述:

马戏团中一共有N个人(N是偶数),有的人会扮演小丑,有的人会表演杂技。给出每个人会什么,然后按照下列规则把这些人分成两组:
  • 每个人只能在其中一组
  • 两个组的人数相等(也就是把这些人分半)
  • 在第一个组会扮演小丑的人的数量,等于在第二个组会表演杂技的数量
输出:被分配在第一个组的人(每个人对应一个下标,输出相应的下标)

题目分析:

前言:这道题刚开始还以为是贪心解决,但是由于博主太渣,用贪心过不了(这里我简单说一下我的贪心思路:把:只会扮演小丑的人放在第二组,只会表演杂技的人放在第一组,然后分类讨论??)。看了官方题解后,竟然是用数学解决→_→。
 
首先,根据题意,我们可以知道一共有四种人:
1.只会扮演小丑的人
2.只会表演杂技的人
3.既会扮演小丑,又会表演杂技的人
4.什么都不会的人
这里我们先要理解好题意:
对于第一种人,如果放在第一组,那么在第一个组会扮演小丑的人的数量就会+1。第一种人可不可以放在第二组?可以,注意到题目只是说要符合数量相等,而没有强制要求第一组的人一定要会扮演小丑,第二组的人一定要会表演杂技。所以第一种人可以放在第二组,只是放在第二组没有“贡献”(这里的“贡献”:在第二个组会表演杂技的数量+1)而已。对于其他的人都有类似的情况。
既然是这样,那么岂不是可以直接贪心做出来?不过,这里我们不研讨贪心的做法,这个可以自己回去想一想。我们可以再看看题目的数据:2≤n≤5000,所以有什么更简单直接暴力的方法???
 
的确是有:根据给出的数据,我们可以很快统计出四种人的人数,我们可以用一些变量表示:
第一种人:only_c
第二种人:only_a
第三种人:both_ca
第四种人:not_ca
统计完后,我们假设在第一组这四种人的数量:
第一种人:c_num
第二种人:a_num
第三种人:b_num
第四种人:n_num
由题易得两个等式:
c_num + a_num + b_num + n_num == n / 2    (第一组人的数量)
c_num + b_num == (only_a - a_num)  +  (both_ca - b_num)    (第一个组会扮演小丑的人的数量,等于第二个组会表演杂技的数量)
这里有四个未知量(c_num, a_num, b_num, n_num),两个方程(等式),所以怎样解方程?
我们知道,像这种情况,方程没有唯一解。但是有多种解啊,所以我们只要求出一个符合题意的方程的解就可以了,那么怎么求?
假如我们确定了四个未知量的其中两个未知量,这时就变成了简单的二元方程了,然后另外两个未知量是不是就解出来了?我们可以这样化简方程:(这里我为了方便选择了c_num和b_num作为自由变量,选其他作为自由变量也没有影响)
c_num = c_num
a_num = only_a + both_ca - 2 * b_num - c_num
b_num = b_num
n_num = n / 2 - only_a - both_ca + b_num
写成这个样子,是不是每个变量都可以用c_num和b_num来表示?接下来就是要确定c_num和b_num要取什么值。
c_num范围:[0, only_c],b_num范围:[0, both_ca]。那么是不是意味着随便取c_num和b_num的值,比如直接取c_num = 0,b_num = 0?当然不是,c_num的值和b_num的值除了要在范围内,还要满足它们的解(a_num和n_num)合法,也就是说,带入c_num和b_num的值进方程后,解出来的a_num范围[0, only_a],n_num范围[0, not_ca]。因此,我们暴力枚举c_num和b_num的值产生的所有可能,看哪些解是合法的,最后答案取合法的解就行了。
 
 
AC代码:
 1 #include <bits/stdc++.h>
2 using namespace std;
3 char clo[5005], acr[5005];
4 int type[5005];
5 int n;
6 int only_c, only_a, both_ca, not_ca;
7
8 bool in(int x, int l, int r){
9 if(l <= x && x <= r) return true;
10 return false;
11 }
12
13 int main(){
14 scanf("%d", &n);
15 scanf("%s%s", clo, acr);
16
17 for(int i = 0; i < n; i++){
18 if(clo[i] == '1' && acr[i] == '0') only_c++, type[i] = 1;
19 if(clo[i] == '0' && acr[i] == '1') only_a++, type[i] = 2;
20 if(clo[i] == '1' && acr[i] == '1') both_ca++, type[i] = 3;
21 if(clo[i] == '0' && acr[i] == '0') not_ca++, type[i] = 4;
22 }
23
24 int c_num, a_num, b_num, n_num;
25 int sus = 0;
26 for(c_num = 0; c_num <= only_c; c_num++){
27 for(b_num = 0; b_num <= both_ca; b_num++){
28 a_num = only_a + both_ca - 2 * b_num - c_num;
29 n_num = n / 2 - only_a - both_ca + b_num;
30 if(in(a_num, 0, only_a) && in(n_num, 0, not_ca)){
31 sus = 1;
32 break;
33 }
34 }
35 if(sus) break;
36 }
37
38 if(sus == 0) {
39 printf("-1");
40 return 0;
41 }
42
43 int c_cnt, a_cnt, b_cnt, n_cnt;
44 c_cnt = a_cnt = b_cnt = n_cnt = 0;
45 for(int i = 0; i < n; i++){
46 sus = 0;
47 if(type[i] == 1 && c_cnt < c_num)
48 c_cnt++, sus = 1;
49 if(type[i] == 2 && a_cnt < a_num)
50 a_cnt++, sus = 1;
51 if(type[i] == 3 && b_cnt < b_num)
52 b_cnt++, sus = 1;
53 if(type[i] == 4 && n_cnt < n_num)
54 n_cnt++, sus = 1;
55
56 if(sus) printf("%d ", i+1);
57 }
58 return 0;
59 }

不行,这个写的太丑,再继续写:

 1 #include <bits/stdc++.h>
2 using namespace std;
3 char c[5005], a[5005];
4 int only_c, only_a, both_ca, not_ca;
5 int st[10][5005]; //栈?
6 int num[10]; //存n_num(num[0]),a_num(num[1]),c_num(num[2]),b_num(num[3])
7 int n;
8
9 bool in(int x, int l, int r){
10 if(l <= x && x <= r) return true;
11 return false;
12 }
13
14 int main(){
15 scanf("%d", &n);
16 scanf("%s%s", c+1, a+1);
17 for(int i = 1; i <= n; i++){
18 //预处理一下
19 c[i] -= '0', a[i] -= '0';
20 }
21
22 int t;
23 for(int i = 1; i <= n; i++){
24 t = c[i]*2 + a[i]; //二进制思想??
25 if(t == 0) st[t][not_ca++] = i;
26 if(t == 1) st[t][only_a++] = i;
27 if(t == 2) st[t][only_c++] = i;
28 if(t == 3) st[t][both_ca++] = i;
29 }
30
31 int sus = 0;
32 for(num[2] = 0; num[2] <= only_c; num[2]++){
33 for(num[3] = 0; num[3] <= both_ca; num[3]++){
34 num[1] = only_a + both_ca - 2*num[3] - num[2];
35 num[0] = n/2 - (num[1]+num[2]+num[3]); //算出num[1]后可以直接这样算num[0]
36 if(in(num[0], 0, not_ca) && in(num[1], 0, only_a)){
37 sus = 1;
38 break;
39 }
40 }
41 if(sus) break;
42 }
43
44 //找不到解
45 if(sus == 0) {
46 printf("-1");
47 return 0;
48 }
49
50 //输出答案
51 for(int i = 0; i < 4; i++){
52 for(int j = 0; j < num[i]; j++){
53 printf("%d ", st[i][j]);
54 }
55 }
56 return 0;
57 }
 
 
 
 
 
 

Codeforces Round #545 B. Circus的更多相关文章

  1. Codeforces Round #545 Div1 题解

    Codeforces Round #545 Div1 题解 来写题解啦QwQ 本来想上红的,结果没做出D.... A. Skyscrapers CF1137A 题意 给定一个\(n*m\)的网格,每个 ...

  2. Codeforces Round #545 (Div. 1) 简要题解

    这里没有翻译 Codeforces Round #545 (Div. 1) T1 对于每行每列分别离散化,求出大于这个位置的数字的个数即可. # include <bits/stdc++.h&g ...

  3. Codeforces Round #545 (Div. 2)(B. Circus)

    题目链接:http://codeforces.com/contest/1138/problem/B 题目大意:贼绕口的题目,就是给你两个字符串s1,s2,然后每一个人代表一列,第一列代表技能一每个人是 ...

  4. CodeForces Round #545 Div.2

    A. Sushi for Two 代码: #include <bits/stdc++.h> using namespace std; ; ; int a[maxn], vis[maxn]; ...

  5. Codeforces Round #545 (Div. 2) D 贪心 + kmp

    https://codeforces.com/contest/1138/problem/D 题意 两个01串s和t,s中字符能相互交换,问最多能得到多少个(可交叉)的t 题解 即将s中的01塞进t中, ...

  6. Codeforces Round #545 (Div. 2) D

    链接:http://codeforces.com/contest/1138/problem/D 啊啊啊啊啊啊,自闭啊,比赛的时候判断条件 if(s1[i-1]=='0') aa++;写成了 if(s1 ...

  7. Codeforces Round #545 (Div. 2)(D. Camp Schedule)

    题目链接:http://codeforces.com/contest/1138/problem/D 题目大意:给你两个字符串s1和s2(只包含0和1),对于s1中,你可以调换任意两个字符的位置.问你最 ...

  8. Codeforces Round #545 (Div. 2) 题解

    题目链接 A. Sushi for Two 题意 在一个 01 序列中找出长为偶数的连续的一段使得它前一半和后一半内部分别相同,而前一半和后一半不同. \(2\le n\le 100\ 000\) 题 ...

  9. Codeforces Round #545 (Div. 2) E 强连通块 + dag上求最大路径 + 将状态看成点建图

    https://codeforces.com/contest/1138/problem/E 题意 有n个城市(1e5),有m条单向边(1e5),每一周有d天(50),对于每个城市假如在某一天为1表示这 ...

随机推荐

  1. 数据分析常用库(numpy,pandas,matplotlib,scipy)

    概述 numpy numpy(numeric python)是 python 的一个开源数值计算库,主要用于数组和矩阵计算.底层是 C 语言,运行效率远高于纯 python 代码.numpy主要包含2 ...

  2. Linux 驱动框架---input子系统框架

    前面从具体(Linux 驱动框架---input子系统)的工作过程学习了Linux的input子系统相关的架构知识,但是前面的学习比较实际缺少总结,所以今天就来总结一下输入子系统的架构分层,站到远处来 ...

  3. Makefile 流程控制(error,warning)等调试选项

    1.退出码 0 ok1 错误2 使用了-q 选项 且目标不需要更新 返回2 2.选项 -f --file 指定makefile脚本 -n --just-print --dry -run -- reco ...

  4. iOS effect & swiper delete components

    iOS effect & swiper delete components mint-ui & cell-swipe https://elemefe.github.io/mint-ui ...

  5. 从崩溃的选课系统,论为什么更安全的 HTTPS 协议没有被全面采用

    尽人事,听天命.博主东南大学研究生在读,热爱健身和篮球,正在为两年后的秋招准备中,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 C ...

  6. 10_MySQL数据表的基本查询

    为了更好的练习数据表的操作,我们需要有些数据来供我们练习,这里给大家分享一份数据,大家可以拿去自己练习使用. 文件地址:https://files.cnblogs.com/files/waterr/d ...

  7. SSL/TLS协议详解(下)——TLS握手协议

    本文转载自SSL/TLS协议详解(下)--TLS握手协议 导语 在博客系列的第2部分中,对证书颁发机构进行了深入的讨论.在这篇文章中,将会探索整个SSL/TLS握手过程,在此之前,先简述下最后这块内容 ...

  8. [Python] 茎叶图和复合饼图的画法

    目录 茎叶图 复合饼图 茎叶图 from itertools import groupby nums2=[225, 232,232,245,235,245,270,225,240,240,217,19 ...

  9. Elasticsearch---DSL搜索实践

    Domain Specific Language 特定领域语言,基于JSON格式的数据查询,查询更灵活,有利于复杂查询 一.普通url路径参数搜索 数据准备 1.建立名字为 shop 的索引 2.手动 ...

  10. 微信小程序优化:实现picker组件中input输入框禁止输入,而只能通过picker组件选择日期

    原来的代码如下: <view class="right">     <picker mode="date" value="{{mat ...