區(qū)間DP

模板
區(qū)間dp一般由小區(qū)間推出大的區(qū)間:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[1010][1010];
int main()
{
for(int i=0;i<n;i++)
 dp[i][i]=........
 
    for(int len=1;len<=n;len++)//區(qū)間長度
    {
        for(int i=0;i<n;i++)//區(qū)間起點(diǎn)
        {
            j=len-1+i;//區(qū)間終點(diǎn)
            for(int k=i;k<j;k++)//k把[i,j]分為[i,k],[k+1,j]
            {
                dp[i][j]=........
            }
        }
    }

http://acm.hdu.edu.cn/showproblem.php?pid=5115
http://blog.csdn.net/JACK_JYH/article/details/52151502

題目大意:你是一個戰(zhàn)士現(xiàn)在面對哈踱,一群狼互妓,每只狼都有一定的主動攻擊力和附帶攻擊力煌妈。你殺死一只狼。你會受到這只狼的(主動攻擊力+旁邊兩只狼的附帶攻擊力)這么多傷害~現(xiàn)在問你如何選擇殺狼的順序使的殺完所有狼時程癌,自己受到的傷害最小。(提醒轴猎,狼殺死后就消失嵌莉,身邊原本相隔的兩只狼會變成相鄰,而且不需要考慮狼圍城環(huán)這種情況)
輸入要求:總共T組數(shù)據(jù)捻脖,每組N只狼锐峭,按順序輸入全部狼的主動攻擊力和然后再按順序輸入全部狼的附帶攻擊力
輸出要求:Case #x: y x第幾組數(shù)據(jù),y最少受到的傷害

#include<stdio.h>
#include <string.h>
#include<algorithm>
using namespace std;
#define maxn 205
int attack[maxn],assit[maxn];
int dp[maxn][maxn];
int main()
{
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",attack+i);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",assit+i);
        }
        assit[0]=0;
        assit[n+1]=0;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
                dp[i][j]=0x3f3f3f3f;
        }//合法區(qū)間設(shè)置為無窮大可婶,其他全部設(shè)置為0
        for(int  r=1;r<=n;r++)
        {
            for(int i=1;i<=n-r+1;i++)
            {
                int j=i+r-1;
                for(int k=i;k<=j;k++)//設(shè)k為最后一只被殺死的狼
                {
                    dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+attack[k]+assit[i-1]+assit[j+1]);
                }
            }
        }
        printf("Case #%d: %d\n",cas,dp[1][n]);
    }
}

http://acm.hdu.edu.cn/showproblem.php?pid=5900
http://www.cnblogs.com/littlepear/p/5886036.html

題意:給n個數(shù)有key和val沿癞,相鄰的并且key不互質(zhì)的兩個數(shù)可以消去并得到val,問最大價值和.
題解:狀態(tài)轉(zhuǎn)移有兩個來源扰肌,第一個是假若一個區(qū)間[i抛寝,j]里面的物品被抽光之后,而且key[i-1]和key[j+1]滿足題目條件的話曙旭,那么answer[i-1][i+1]=max(answer[i][j]+value[i]+value[j],answer[i][j]).假若在區(qū)間里面還剩下幾個不能被抽走盗舰,區(qū)間[i,j]的最大值就相當(dāng)于兩個區(qū)間直接拼在一起嘍answer[i][j]=max(answer[i][j],answer[i][k]+answer[k+1][j]).要判斷區(qū)間[i,j]里的物品是否全都被抽光只需判定answer[i][j]==∑(k=i→ j)value[k]即可,為了這個的判斷方便桂躏,這里特地的把value做成了前綴和的形式钻趋,方便判斷

#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 305
using namespace std;
typedef long long ll;
ll dp[maxn][maxn], key[maxn], val[maxn],sum[maxn];
ll gcd(ll a,ll b)
{
    return b == 0 ? a : gcd(b, a % b);
}
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        sum[0]=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%I64d",&key[i]);
        for(int i=1;i<=n;i++) scanf("%I64d",&val[i]),sum[i]=val[i]+sum[i-1];
        memset(dp,0,sizeof(dp));
    for(int l=2;l<=n;l++)
    {
        for(int i=1;i+l<=n+1;i++)
        {
            int j=i+l-1;
            for(int k=i;k<j;k++)
                dp[i][j] = max(dp[i][j],dp[i][k]+dp[k+1][j]);
            if(gcd(key[i],key[j])>1)
            {
                if(j==i+1) dp[i][j] = val[i]+val[j];
                else if(dp[i+1][j-1]==sum[j-1]-sum[i]) dp[i][j] = max(dp[i][j],dp[i+1][j-1]+val[i]+val[j]);
            }
        }
    }
    printf("%I64d\n",dp[1][n]);
    }
}

http://acm.hdu.edu.cn/showproblem.php?pid=4283

有n個男屌絲事先按1,2,3,,,,,,n的順序排好,每個人都有一個不開心值unhappy[i]剂习,如果第i個人第k個上臺找對象蛮位,那么該屌絲男的不開心值就會為(k-1)unhappy[i],因?yàn)樵谒懊嬗衚-1個人嘛鳞绕,導(dǎo)演為了讓所有男屌的總不開心值最小失仁,搞了一個小黑屋,可以通過小黑屋來改變男屌的出場順
们何。這個小黑屋是個棧萄焦,男屌的順序是排好了的,但是可以通過入棧出棧來改變男屌的出場順序
那么對于dp[i][j]的第i個人,就有可能第1個上場拂封,也可以第j-i+1個上場茬射。考慮第K個上場
即在i+1之后的K-1個人是率先上場的冒签,那么就出現(xiàn)了一個子問題 dp[i+1][i+1+k-1-1]表示在第i個人之前上場的.對于第i個人在抛,由于是第k個上場的,那么憤怒值便是val[i]
(k-1).其余的人是排在第k+1個之后出場的萧恕,也就是一個子問題dp[i+k][j]刚梭,對于這個區(qū)間的人,由于排在第k+1個之后廊鸥,所以整體憤怒值要加上k*(sigma(i+k--j))望浩。

#include<cstdio>
#include<string.h>
#include<cstring>
#include<algorithm>
#define maxn 105
using namespace std;
int dp[maxn][maxn],sum[maxn],arr[maxn];
int main()
{

    int n,t;
    scanf("%d",&t);
    for(int q=1;q<=t;q++)
    {
        scanf("%d",&n);
        sum[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",arr+i);
            sum[i]=sum[i-1]+arr[i];
        }
        memset(dp,0,sizeof dp);
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                dp[i][j]=0x3f3f3f;
            }
        }
        for(int r=1;r<=n;r++)
        {
            for(int i=1;i<=n-r+1;i++)
            {
                int j=i+r-1;
                for(int k=1;k<=r;k++)
                {
                    dp[i][j]=min(dp[i][j],dp[i+1][i+k-1]+arr[i]*(k-1)+dp[i+k][j]+(sum[j]-sum[i+k-1])*k);
                }
            }
        }
        printf("Case #%d: %d\n",q,dp[1][n]);
    }
}

石子合并 直線型

有N堆石子排成一排,每堆石子有一定的數(shù)量《杷担現(xiàn)要將N堆石子并成為一堆磨德。合并的過程只能每次將相鄰的兩堆石子堆成一堆,每次合并花費(fèi)的代價為這兩堆石子的和吆视,經(jīng)過N-1次合并后成為一堆典挑。求出總的代價最小值。

#include<cstdio>
#include<string.h>
#include<algorithm>
#define maxn 205
using namespace std;
int dp[maxn][maxn],sum[maxn],arr[maxn];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        sum[0]=0;
        for(int i=1;i<=n;i++)
        {
            //dp[i][i]=0;
            scanf("%d",arr+i);
            sum[i]=sum[i-1]+arr[i];
        }
        memset(dp,0x3f3f3f,sizeof(dp));
        for(int i=1;i<=n;i++)
            dp[i][i]=0;
        for(int r=2;r<=n;r++)
        {
            for(int i=1;i<=n-r+1;i++)
            {
                int j=i+r-1;
                dp[i][j]=dp[i][i]+dp[i+1][j]+sum[j]-sum[i-1];
                for(int k=2;k<j;k++)
                {
                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
                }
            }
        }
        printf("%d\n",dp[1][n]);
    }
}

石子合并 環(huán)形
SCUT OJ 1207 http://www.scut.edu.cn/oj

#include<cstdio>
#include<string.h>
#include<algorithm>
#define maxn 105
using namespace std;
int dp[maxn][maxn],dp2[maxn][maxn],sum[maxn][maxn],num[maxn];
int main()
{
   int n;
   while(scanf("%d",&n)!=EOF,n)
   {
       for(int i=1;i<=n;i++)
       {
           scanf("%d",num+i);
       }
       for(int i=1;i<=n;i++)
           sum[i][1]=num[i];
       for(int j=2;j<=n;j++)
       {
           for(int i=1;i<=n;i++)
               sum[i][j]=sum[i%n+1][j-1]+num[i];
       }
       for(int i=0;i<=n;i++)
           dp[i][1]=dp2[i][1]=0;
       for(int r=2;r<=n;r++)
       {
           for(int i=1;i<=n;i++)
           {
               dp2[i][r]=0;
               dp[i][r]=0x3f3f3f3f;
               for(int k=1;k<r;k++)
               {
                   dp[i][r]=min(dp[i][r],dp[i][k]+dp[(i+k-1)%n+1][r-k]+sum[i][r]);
                   dp2[i][r]=max(dp2[i][r],dp2[i][k]+dp2[(i+k-1)%n+1][r-k]+sum[i][r]);
               }
           }
       }
       int minv=0x3f3f3f3f,maxv=0;
       for(int i=1;i<=n;i++)
       {
           maxv=maxv<dp2[i][n]?dp2[i][n]:maxv;
           minv=minv>dp[i][n]?dp[i][n]:minv;
       }
       printf("%d %d\n",minv,maxv);
   }
}

最大k乘積

設(shè)I是一個n位十進(jìn)制整數(shù)啦吧。如果將I劃分為k段您觉,則可得到k個整數(shù)。這k個整數(shù)的乘積稱為I的一個k乘積授滓。試設(shè)計一個算法琳水,對于給定的I和k,求出I的最大k乘積般堆。

#include<cstdio>
#include<string.h>
#include<algorithm>
#define maxn 15
using namespace std;
int bit[maxn];
long long dp[maxn][maxn],val[maxn][maxn];
/*
num:1345
bit[1]=1,bit[2]=3,bit[3]=4,bit[4]=5;
dp[i][j]:1-i位的最大j乘積
val[s][len] :第s位開始的長度為len的數(shù)字組成的10進(jìn)制數(shù)(包含s位)
dp[i][j]=max(dp[k][j-1]*val[k][j-k]) ,1<=k<i;
*/
int main(void)
{
    int n,k,num,i=0,j,m;
    long long maxv;
    char str[15];
   while(scanf("%d%d",&n,&k)!=EOF)
   {
    scanf("%s",str);
    for(i=0;i<n;i++)
        bit[i+1]=str[i]-'0';
    memset(val,0,sizeof(val));
    for(i=1;i<=n;i++)
    {
        long long ans=0;
        for(int len=1;len+i-1<=n;len++)
        {
            ans=ans*10+bit[i+len-1];
            val[i][len]=ans;
        }
    }
    memset(dp,0,sizeof(dp));
    for(i=1;i<=n;i++)
        dp[i][1]=val[1][i];
    for(i=2;i<=n;i++)
        for(j=2;j<=k;j++)
        {
            for(m=1;m<i;m++)
                dp[i][j]=max(dp[i][j],dp[m][j-1]*val[m+1][i-m]);
        }
        printf("%lld\n",dp[n][k]);
   }
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末在孝,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子淮摔,更是在濱河造成了極大的恐慌私沮,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件和橙,死亡現(xiàn)場離奇詭異仔燕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)魔招,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門晰搀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人办斑,你說我怎么就攤上這事厕隧。” “怎么了俄周?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵吁讨,是天一觀的道長。 經(jīng)常有香客問我峦朗,道長建丧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任波势,我火速辦了婚禮翎朱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尺铣。我一直安慰自己拴曲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布凛忿。 她就那樣靜靜地躺著澈灼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪店溢。 梳的紋絲不亂的頭發(fā)上叁熔,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機(jī)與錄音床牧,去河邊找鬼荣回。 笑死,一個胖子當(dāng)著我的面吹牛戈咳,可吹牛的內(nèi)容都是我干的心软。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼著蛙,長吁一口氣:“原來是場噩夢啊……” “哼删铃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起册踩,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤泳姐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后暂吉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胖秒,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年慕的,在試婚紗的時候發(fā)現(xiàn)自己被綠了阎肝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡肮街,死狀恐怖风题,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤沛硅,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布眼刃,位于F島的核電站,受9級特大地震影響摇肌,放射性物質(zhì)發(fā)生泄漏擂红。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一围小、第九天 我趴在偏房一處隱蔽的房頂上張望昵骤。 院中可真熱鬧,春花似錦肯适、人聲如沸变秦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹦玫。三九已至,卻和暖如春雨饺,著一層夾襖步出監(jiān)牢的瞬間钳垮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工额港, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饺窿,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓移斩,卻偏偏與公主長得像肚医,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子向瓷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容