1. 程式人生 > 實用技巧 >洛谷 P1877 [HAOI2012]音量調節 (dp)

洛谷 P1877 [HAOI2012]音量調節 (dp)

題目描述

一個吉他手準備參加一場演出。他不喜歡在演出時始終使用同一個音量,所以他決定每一首歌之前他都需要改變一次音量。在演出開始之前,他已經做好一個列表,裡面寫著每首歌開始之前他想要改變的音量是多少。每一次改變音量,他可以選擇調高也可以調低。

音量用一個整數描述。輸入檔案中整數beginLevel,代表吉他剛開始的音量,整數maxLevel,代表吉他的最大音量。音量不能小於00也不能大於maxLevel。輸入中還給定了n個整數c1,c2,c3,,cn,表示在第ii首歌開始之前吉他手想要改變的音量是多少。

吉他手想以最大的音量演奏最後一首歌,你的任務是找到這個最大音量是多少。

輸入格式

第一行依次為三個整數n,beginLevel和maxLevel。

第二行依次為n個整數c1,c2,c3,,cn

輸出格式

輸出演奏最後一首歌的最大音量。如果吉他手無法避免音量低於0或者高於maxLevel,輸出-1

輸入輸出樣例

輸入 #1
3 5 10
5 3 7
輸出 #1
10

說明/提示

1n50,1cimaxLevel,1maxLevel1000,0beginLevelmaxLevel。

一道到達型的01揹包問題

用dp [ i ] [ j ]表示經過i次操作,音量能否到達 j。0表示不能,1表示能。

如果第 i - 1 次操作後可以達到 j,那麼第i次操作可以到達 j - n [ i ] 和 j + n [ i ]。當然了,也要考慮是否越界。至此,狀態轉移方程已經寫出來了。

#include<iostream>
#include<cstdio>
using namespace std;
bool dp[55][1005];

int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0'
; ch=getchar(); } return x*f; } int main() { int a=read(),begin=read(),maxl=read(); int n[a+1]; for(int i=1;i<=a;i++) n[i]=read(); dp[0][begin]=1; for(int i=1;i<=a;i++) for(int j=0;j<=maxl;j++) if(dp[i-1][j]) { if(j+n[i]<=maxl) dp[i][j+n[i]]=1; if(j-n[i]>=0) dp[i][j-n[i]]=1; } for(int i=maxl;i>=0;i--) if(dp[a][i]) {cout<<i;return 0;} cout<<"-1"; return 0; }
dp