HihoCoder 1527 动态规划

https://hihocoder.com/problemset/problem/1527

时间限制:20000ms

单点时限:1000ms

内存限制:256MB

描述

在写代码时,我们经常要用到类似 x × a 这样的语句( a 是常数)。众所周知,计算机进行乘法运算是非常慢的,所以我们需要用一些加法、减法和左移的组合来实现乘一个常数这个操作。具体来讲, 我们要把 x × a 替换成:(x<<a0) op1 (x<<a1) op2 (x<<a2) ... opn (x<<an) 这样的形式,其中opi 是+或者-。

举个例子:x × 15 = (x<<4) - (x<<0)。

在本题中,假设左移(包括左移0)和加法、减法所需要的时间都是一个单位的时间,上述的例子所需要的时间是3。

现在给定常数 a 的二进制形式,求实现 x × a 最少需要多少单位的时间。

输入

一个01串,表示 a 的二进制形式,从左到右分别是从高位到低位。

0 < 01串的长度之和 ≤ 106

a > 0。

输出

输出一个数,表示最小需要多少单位的时间可以实现 x × a

样例输入
1111
样例输出
3
错解:
贪心选择超过两个连续的1的决策不如使用高位减低位的方法,110不如1<<3 – 1<<1
然后,单个1选择直接加上。
如果两个大块(2个连续1以上)中间之隔为1个0,那么可以合并,110110不如 1<<6 – 1<<4 + 1<<3 – 1<<1 = 1<<6 – 1 <<3 – 1<<1
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <string>
#include <math.h>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-9;
const int N = 1e6 + 5;

char s[N];

int main()

{
    while(scanf("%s", s) != EOF)
    {
        int n = strlen(s);
        int cnt = 0;
        int i = 0;
        while(i < n)
        {
            int k = 0;
            while(i < n && s[i] == ‘1‘)
            {
                k++;
                i++;
            }
            if(k == 1) cnt++;
            else if(k >= 2) cnt += 2;
            if(k >= 2 && i+2 < n && s[i+1] == ‘1‘ && s[i+2] == ‘1‘)
                cnt -= 1;
            if(i < n && s[i] == ‘0‘)
                i++;
        }
        printf("%d\n", 2*cnt-1);
    }
    return 0;
}


题解:很多都是二幂划分的解释,也可以用dp来做
从低位往高位考虑。dp[i]表示第i位的时候需要进行最少操作数
如果当前位是0,dp[i] = dp[i-1]
如果当前位是1,可以有两种选择,直接加上dp[i] = dp[i-1] + 1;
或者,把某一部分的0全部补上,然后用高位1减去,例如01100 = 10000 – 00100,也就是 [x, i]全部都变成1,也就是要补上x~i的0
dp[i] =min{ dp[x-1] + 2 + sum[i] – sum[x-1]}

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <string>
#include <math.h>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-9;
const int N = 1e6 + 5;

char s[N];
int sum[N], dp[N];
int main()
{
    scanf("%s", s+1);
    int n = strlen(s+1);
    memset(dp,0,sizeof(dp));
    memset(sum, 0, sizeof(sum));
    reverse(s+1,s+1+n);
    for(int i = 1; i <= n; i++) sum[i] =sum[i-1] + (s[i] == ‘0‘);
    dp[0] = 0;
    int mx = -1;
    for(int i = 1; i <= n; i++)
    {
        if(s[i] == ‘0‘)
            dp[i] = dp[i-1];
        else
        {
            dp[i] = dp[i-1] + 1;
            if(mx > 0)
                dp[i] = min(dp[i], dp[mx-1] + 2 + sum[i] - sum[mx-1]);
        }
        if(mx == -1 || dp[i-1] + 2 + sum[i+1] - sum[i-1] <= dp[mx-1] + 2 + sum[i+1] - sum[mx-1])
            mx = i;
    }
    printf("%d\n", 2*dp[n]-1);
    return 0;

}

				
时间: 2024-10-27 02:46:50

HihoCoder 1527 动态规划的相关文章

hihoCoder 1527 快速乘法

#include<bits/stdc++.h> using namespace std; const int N = 1e6+5; char a[N]; int main() { scanf("%s",a+1); int n = strlen(a+1); int l = 1,r = n; while(l <= n && a[l] == '0') l++; while(r >= 0 && a[r] == '0') r--; int

Hihocoder #1527 : 快速乘法 DP

时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 在写代码时,我们经常要用到类似 x × a 这样的语句( a 是常数).众所周知,计算机进行乘法运算是非常慢的,所以我们需要用一些加法.减法和左移的组合来实现乘一个常数这个操作.具体来讲, 我们要把 x × a 替换成:(x<<a0) op1 (x<<a1) op2 (x<<a2) ... opn (x<<an) 这样的形式,其中opi 是+或者-. 举个例子:x × 15 = (

ACM学习历程—Hihocoder 1290 Demo Day(动态规划)

http://hihocoder.com/problemset/problem/1290 这题是这次微软笔试的第三题,过的人比第一题少一点,这题一眼看过去就是动态规划,不过转移方程貌似不是很简单,调试了比较久才正确,不过好在是1A,但是最后只留了一个小时多一点给B题,也导致了B题最后也没能AC掉.首先状态是很好确定的p[i][j][k]表示走到第i行第j个格子时,方向是k的情况下的最小改变格子数目.(k from {0, 1})而且由于只有往下和往右走,所以中间过程进行转移时改变的格子不会影响后

[ACM] hihoCoder 1075 开锁魔法III (动态规划,组合数学)

描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它们打开.崔克茜想知道最后所有盒子都被打开的概率,你能帮助她回答这个问题吗? 输入 第一行一个整数 T (T ≤ 100)表示数据组数. 对于每组数据,第一行有两个整数 n 和 k (1?≤?n?≤?300,?0?≤?k?≤?n). 第二行有 n 个整数 ai,表示第 i 个盒子中,装有可以打开第 a

hihoCoder - 1038 - 01背包 (经典动态规划问题!!)

#1038 : 01背包 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 且说上一周的故事里,小Hi和小Ho费劲心思终于拿到了茫茫多的奖券!而现在,终于到了小Ho领取奖励的时刻了! 小Ho现在手上有M张奖券,而奖品区有N件奖品,分别标号为1到N,其中第i件奖品需要need(i)张奖券进行兑换,同时也只能兑换一次,为了使得辛苦得到的奖券不白白浪费,小Ho给每件奖品都评了分,其中第i件奖品的评分值为value(i),表示他对这件奖品的喜好值.现在他想知道,凭借他手上的这

Hihocoder #1075 : 开锁魔法III (组合数学+动态规划)

题目链接 题目大意:有n个箱子,每个箱子中放着一个箱子的钥匙,可以用魔法打开k个箱子,问最终能打开所有箱子的概率是多少. 思路:首先我们想到,如果一组箱子的打开目标能构成一个环,那么这个箱子中只要打开一个就随意了.问概率的话,最好想的做法就是用A事件发生的次数/事件总数.事件总数很好求,就是在n个箱子中选择k个打开:C[n][k]. 然后考虑有多少种合法的打开方式,我开始想的是直接用组合数学乱搞,乘法原理,设一共有tot个环,每个环的大小分别是a1,a2,a3...atot;计算的时候先a1*a

hihoCoder - 1037 - 数字三角形 (动态规划)

#1037 : 数字三角形 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 问题描述 小Hi和小Ho在经历了螃蟹先生的任务之后被奖励了一次出国旅游的机会,于是他们来到了大洋彼岸的美国.美国人民的生活非常有意思,经常会有形形色色.奇奇怪怪的活动举办,这不,小Hi和小Ho刚刚下飞机,就赶上了当地的迷宫节活动.迷宫节里展览出来的迷宫都特别的有意思,但是小Ho却相中了一个其实并不怎么像迷宫的迷宫--因为这个迷宫的奖励非常丰富~ 于是小Ho找到了小Hi,让小Hi帮助他获取尽可能多的

关于动态规划的理解

动态规划是个比较有趣的算法,第一次接触动态规划也是从一个比较特别的教程开始的,这里贴出原文地址http://blog.csdn.net/woshioosm/article/details/7438834 看完原文回到这里,其实我觉得很多像我这种C语言刚刚入门的人,只理解到了动态规划的转移方程,以原文中的例子为例: 当mineNum = 0且people >= peopleNeeded[mineNum]时 f(people,mineNum) = gold[mineNum] 当mineNum = 0

【hihoCoder】1033: 交错和

初探数位dp 介绍了数位类统计的基础知识.以下列出其中的基础点: 基本问题 统计在区间[l, r]中满足条件的数的个数 思路 1. [l, r] 将问题转换为 在[0, r]中满足条件的个数 - 在[0, l)满足条件的个数 2. 求解 区间[0, n]满足条件的个数 性质:一个小于n的数m,一定是从高位到低位在某一位小于n的对应位的一个数   数值 百位 十位 个位   n 358 3 5 8   m 350 3 5 0 0<8 m 349 3 4 9 4<5 遍历所有小于n的数:从高位到低