2020百度之星初赛二 Car(状压DP+二分)

2024-04-16 00:32

本文主要是介绍2020百度之星初赛二 Car(状压DP+二分),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Problem Description
W 市最近面临了严重的交通拥堵问题,现在决定要在工作日(周一到周五)限号。
每天可以限制若干尾号的车辆,譬如说周一限尾号为 0 的车,周二限尾号为 1,2 的车。

每个尾号在五天当中最多只能被限一次,一天也可以什么牌照都不限。

我们要设置一个容量上限 m,使得至少存在一种方案,每一天不被限号的车的总数都小于等于 m。

请求出最小的 m。

Input
第一行一个整数 test(1≤test≤10) 表示数据组数。

对于每组数据,第一行一个正整数 n(1≤n≤10000) 表示这个城市里有多少辆车。

接下来 n 行,每行一个字符串表示车牌。车牌由 5 位字符构成,每位都是’0’-'9’的数字。两辆车的车牌可能相同。

Output
对于每组数据,一行一个整数表示答案。

Sample Input
2
1
00000
10
00000
00001
00002
00003
00004
00005
00006
00007
00008
00009

Sample Output
1
8

Source
2020 年百度之星·程序设计大赛 - 初赛二

思路:
10的范围一眼状压,然后这个结果肯定有单调性,限制越大越容易满足,所以状压dp+二分就好了。只不过状压肯定不能两层for枚举状态,可以枚举超集,复杂度为3^n,这个之前也遇到了很多次了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include <map>
#include <string>
#include <cmath>using namespace std;
typedef long long ll;typedef long long ll;
const int maxn = 1e5 + 7;
const int mod = 1e9 + 7;int a[maxn]; //每个车牌号的数量int n;
int f[11][1 << 11];
int sta[1 << 11];void init() {for(int i = 0;i < (1 << 10);i++) {sta[i] = 0;for(int j = 0;j < n;j++) {if(i & (1 << j)) {sta[i] += a[j];}}}
}bool check(int mid) {memset(f,0x3f,sizeof(f));for(int i = 0;i < (1 << 10);i++) {f[1][i] = n - sta[i];}int cnt = 0;for(int i = 2;i <= 5;i++) { //第几天for(int j = 0;j < (1 << 10);j++) { //前一天状态if(f[i - 1][j] > mid) continue;for(int k = j; k < (1 << 10); k = (k + 1) | j) { //今天状态int num = n - sta[k ^ j];if(num > mid) {continue;}f[i][k] = min(f[i][k],num);}}int flag = 1;for(int j = 0;j < (1 << 10);j++) {if(f[i][j] <= mid) {flag = 0;break;}}if(flag) return false;}for(int i = 0;i < (1 << 10);i++) {if(f[5][i] <= mid) return true;}return false;
}int main() {int T;scanf("%d",&T);while(T--) {scanf("%d",&n);memset(a,0,sizeof(a));for(int i = 1;i <= n;i++) {int x;scanf("%d",&x);x %= 10;a[x]++;}init();int l = 0,r = n;int ans = n;while(l <= r) {int mid = (l + r) >> 1;if(check(mid)) {r = mid - 1;ans = mid;} else {l = mid + 1;}}printf("%d\n",ans);}return 0;
}

这篇关于2020百度之星初赛二 Car(状压DP+二分)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907347

相关文章

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

uva 10154 DP 叠乌龟

题意: 给你几只乌龟,每只乌龟有自身的重量和力量。 每只乌龟的力量可以承受自身体重和在其上的几只乌龟的体重和内。 问最多能叠放几只乌龟。 解析: 先将乌龟按力量从小到大排列。 然后dp的时候从前往后叠,状态转移方程: dp[i][j] = dp[i - 1][j];if (dp[i - 1][j - 1] != inf && dp[i - 1][j - 1] <= t[i]

uva 10118 dP

题意: 给4列篮子,每次从某一列开始无放回拿蜡烛放入篮子里,并且篮子最多只能放5支蜡烛,数字代表蜡烛的颜色。 当拿出当前颜色的蜡烛在篮子里存在时,猪脚可以把蜡烛带回家。 问最多拿多少只蜡烛。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cs