题目链接OvO

题目大意

  给你\(n\)串数字,\(1\)代表该位置是亮的,\(0\)代表是灭的。你必须修改\(k\)个数字,使某些\(0\)变为\(1\)。注意,只能把原来的\(0\)改成\(1\)。

分析

  由于每串数字上的\(1\)是不能修改的,所以每串数字并不一定能完整的表示\(0-9\)之内的所有数,所有需要先对每串数字做一下预处理,计算出能改为哪些数字和修改的代价。然后第一步,我们需要判断是否可以构成\(n\)个完整数字。这个直接来判断似乎不太好做。但是可以转换一下,变成能否只消耗\(k\)构成\(n\)个完整数字。这个类似于背包问题,问能否用\(n\)个数构成\(k\)。

  状态转移方式为:若第\(i\)步可以到达容量\(j\),那么第\(i+1\)步就可以到达\(j+cost[i+1]\)。

  我们将上面稍微变形,不难得出:\(dp[i][j] |= dp[i-1][j-cost[i][t]],0\leq t\leq 9\)。

  所以只要判断\(dp[n][k]\)是否为\(true\)就能知道能否只消耗\(k\)显示\(n\)个完整数字了。但是这还不够,答案还需要输出最大的可能结果。我们通过上面的\(dp\)已经获得了一个状态转移的图,红色终点代表错误的终点,黑色终点代表正确的终点画出来(只是部分)大概是这样子的(这里只有\(end1\)是正确的,其他的要么是容量不为\(k\)(\(end2\)),要么是选的个数不够(\(end3\))):



  我们的\(dp\)数组里存储了从起始点到终点的所有路径,可以看出,只要从终点向起点方向走,一定能走到起点,每次消耗为\(cost[i][t]\)。但是题目要求我们输出答案最大,答案最大的话就要要求大的数字靠前,所以倒着从最后一个数开始贪心肯定是不行的,我们需要正着贪心。那么我们就只能倒着\(dp\),这样我们就得到一个从最后一个数到第一个数的状态转移图。这时候我们只需要从第一个数开始贪心的每步选择能够到达的,代表数字最大的路径就行了。这样的话第一步的状态转移方程就变成了\(dp[i][j] |= dp[i+1][j-cost[i][k]],0\leq t\leq 9\)。

具体实现

第一步

  先预处理,求每串数变成每个数字的消耗,显示不了的数字消耗就是\(-1\),存入\(cost\)数组中。

    char nums[][10] = {"1110111","0010010","1011101","1011011","0111010","1101011","1101111","1010010","1111111","1111011"};
char str[maxn][10];
void solve(int pos) {
for (int i = 9; i>=0; --i) {
int cnt = 0;
for (int j = 0; j<7; ++j) {
if (str[pos][j]=='1'&&nums[i][j]=='0') {
cnt = -1;
break;
}
if (str[pos][j]=='0'&&nums[i][j]=='1') ++cnt;
}
cost[pos][i] = cnt;
}
}

第二步

  根据\(dp[i][j] |= dp[i+1][j-cost[i][k]],0\leq t\leq 9\)倒着得到\(dp\)数组的值。

        dp[n+1][0] = true;
for (int i = n; i>=1; --i)
for (int k = 9; k>=0; --k)
if (~cost[i][k])
for (int j = m; j>=cost[i][k]; --j)
dp[i][j] |= dp[i+1][j-cost[i][k]];
if (!dp[1][m]) {
cout << -1 << endl;
return 0;
}

第三步

  正着贪心得到最大可能的数字。

        for (int i = 1; i<=n; ++i)
for (int j = 9; j>=0; --j)
if (~cost[i][j] && m>=cost[i][j] && dp[i+1][m-cost[i][j]]) {
cout << j;
m -= cost[i][j];
break;
}

完整代码

    const int maxn = 2e3+10;
char nums[][10] = {"1110111","0010010","1011101","1011011","0111010","1101011","1101111","1010010","1111111","1111011"};
char str[maxn][10];
int n, m, dp[maxn][maxn], cost[maxn][10];
void solve(int pos) {
for (int i = 9; i>=0; --i) {
int cnt = 0;
for (int j = 0; j<7; ++j) {
if (str[pos][j]=='1'&&nums[i][j]=='0') {
cnt = -1;
break;
}
if (str[pos][j]=='0'&&nums[i][j]=='1') ++cnt;
}
cost[pos][i] = cnt;
}
}
int main(void) {
cin >> n >> m;
for (int i = 1; i<=n; ++i) {
cin >> str[i];
solve(i);
}
dp[n+1][0] = true;
for (int i = n; i>=1; --i)
for (int k = 9; k>=0; --k)
if (~cost[i][k])
for (int j = m; j>=cost[i][k]; --j)
dp[i][j] |= dp[i+1][j-cost[i][k]];
if (!dp[1][m]) {
cout << -1 << endl;
return 0;
}
for (int i = 1; i<=n; ++i)
for (int j = 9; j>=0; --j)
if (~cost[i][j] && m>=cost[i][j] && dp[i+1][m-cost[i][j]]) {
cout << j;
m -= cost[i][j];
break;
}
cout << endl;
return 0;
}

Codeforces 1340B Nastya and Scoreboard(dp,贪心)的更多相关文章

  1. CF#637 D. Nastya and Scoreboard DP

    D. Nastya and Scoreboard 题意 一块电子屏幕上有n个数字. 每个数字是通过这样7个线段显示的,现在你不小心打坏了k个线段,给出打坏之后的n个数字的显示方式,问之前的屏幕表示的最 ...

  2. Codeforces 1136D - Nastya Is Buying Lunch - [贪心+链表+map]

    题目链接:https://codeforces.com/problemset/problem/1136/D 题意: 给出 $1 \sim n$ 的某个排列 $p$,再给出若干 $(x,y)$ 表示当序 ...

  3. Codeforces 1136D Nastya Is Buying Lunch (贪心)

    题意: 给一个序列和一组交换序列(a,b),当且仅当a在b的前面(不允许有间隔),这两个数才能交换,问最后一个数最多能移动多少个位置. 分析: 这题是思路是十分的巧妙呀 , 用一个数组num[x]  ...

  4. Codeforces 437C The Child and Toy(贪心)

    题目连接:Codeforces 437C  The Child and Toy 贪心,每条绳子都是须要割断的,那就先割断最大值相应的那部分周围的绳子. #include <iostream> ...

  5. Codeforces Round #546 (Div. 2) D 贪心 + 思维

    https://codeforces.com/contest/1136/problem/D 贪心 + 思维 题意 你面前有一个队列,加上你有n个人(n<=3e5),有m(m<=个交换法则, ...

  6. 【bzoj4027】[HEOI2015]兔子与樱花 树形dp+贪心

    题目描述 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接,我们可以把它 ...

  7. BZOJ 2021 [Usaco2010 Jan]Cheese Towers:dp + 贪心

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2021 题意: John要建一个奶酪塔,高度最大为m. 他有n种奶酪.第i种高度为h[i]( ...

  8. [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)

    [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...

  9. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

随机推荐

  1. SG函数(斐波那契博弈) Fibonacci again and again

    https://zhuanlan.zhihu.com/p/53948422 HDU - 1848 将这篇文章认真的看了一遍 ,虽然不是很懂 ,但是脑子里有了一个模型,链接里的图 (看的顺序 是 0,1 ...

  2. 面试指南」JS 模块化、组件化、工程化相关的 15 道面试题

    JS 模块化.组件化.工程化相关的 15 道面试题 1.什么是模块化? 2.简述模块化的发展历程? 3.AMD.CMD.CommonJS 与 ES6 模块化的区别? 4.它们是如何使用的? 5.exp ...

  3. 140行Python代码实现Flippy Bird

    140行代码实现Flippy Bird 话说这游戏中文名叫什么来着,死活想不起来了,算了话不多说,140行实现小游戏系列第二章,依然是简单小游戏,与数独游戏相比,在游戏界面显示上更难一些,但是在逻辑方 ...

  4. 算法(algorithm)

    算法是什么? 算法是指令的集合,是为解决特定问题而规定的一系列操作. 它是明确定义的可计算过程,以一个数据集合作为输入,并产生一个数据集合作为输出. 一个算法通常来说具有以下五个特性: 1.输入:一个 ...

  5. python 报错:a bytes-like object is required, not 'str'

    核心代码: def ipPools(numPage): headers = randomHeads() url = 'http://www.xicidaili.com/nn/' saveFsvFile ...

  6. NKOJ 1353 图形面积

    时间限制 : 10000 MS   空间限制 : 65536 KB 问题描述 桌面上放了N个矩形,这N个矩形可能有互相覆盖的部分,求它们组成的图形的面积.(矩形的边都与坐标轴平行) 输入格式 输入第一 ...

  7. JSP+SSH+Mysql+C3P0实现的传智播客网上商城

    项目简介 项目来源于:https://gitee.com/2121/shop 本系统是传智播客授课时的开发案例,基于JSP+SSH+Mysql的简单网上商城.在当代开发中,SSH的使用已经逐渐被SSM ...

  8. Kylin 初入门 | 从下载安装到体验查询

    本文旨在为 Kylin 新手用户提供一份从下载安装到体验亚秒级查询的完整流程.文章分为两个部分,分别介绍了有 Hadoop 环境(基于 Hadoop 环境的安装)和没有 Hadoop 环境(从 Doc ...

  9. PTA | 1019 数字黑洞 (20分)

    给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字.一直重复这样做,我们很快会停在有" ...

  10. python中使用163邮箱发送邮件一直报错的问题,谁能解决(已经各种百度完了,没能解决问题)

    1.报错如下: 2.代码如下: