1. 程式人生 > >HihoCoder 1527 動態規劃

HihoCoder 1527 動態規劃

mes 減法 二進制 set turn eof lib 長度 print

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;

}

HihoCoder 1527 動態規劃