动态规划专题

一、简单基础dp

1、递推:

hdu 2084 数塔 

 1 #include <iostream>
 2 #include <map>
 3 #include <stack>
 4 #include <deque>
 5 #include <queue>
 6 #include <vector>
 7 #include <set>
 8 #include <algorithm>
 9 #include <cstring>
10 #include <cstdio>
11 using namespace std;
12 const int N=105;
13 int t, n;
14 int tow[N][N];
15 void cal()
16 {
17     for(int i=n-2; i>=0; i--)
18         for(int j=0; j<=i; j++)
19             tow[i][j]+=max(tow[i+1][j],tow[i+1][j+1]);
20 }
21 int main()
22 {
23     //freopen("input.txt", "r", stdin);
24     cin>>t;
25     while(t--)
26     {
27         memset(tow, 0, sizeof(tow));
28         cin>>n;
29         for(int i=0; i<n; i++)//输入
30             for(int j=0; j<=i; j++)
31                 scanf("%d",&tow[i][j]);
32         cal();
33         cout<<tow[0][0]<<endl;
34     }
35     return 0;
36 }
HDU2084

 hdu 2018 母牛的故事  每年的牛数量=去年的已成年牛*2 + 今年刚好成年的牛*2 + 还未成年的牛。 (假设牛成年时立刻生牛仔)

 1 #include <iostream>
 2 #include <map>
 3 #include <stack>
 4 #include <deque>
 5 #include <queue>
 6 #include <vector>
 7 #include <set>
 8 #include <algorithm>
 9 #include <cstring>
10 #include <cstdio>
11 using namespace std;
12 const int N=56;
13 int t;
14 int num[N];
15 int chi[N];
16 int bir[N];
17 void cal()
18 {
19     num[1]=1;num[2]=2;num[3]=3;
20              chi[2]=1;chi[3]=2;
21              bir[2]=1;bir[3]=1;
22     for(int i=4; i<N; i++)
23     {
24         int tmp1=num[i-1]-chi[i-1];
25         int tmp2=chi[i-1]-bir[i-3];
26         num[i]= (tmp1<<1) + (bir[i-3]<<1) + tmp2 ;    //已成年*2 + 刚好成年*2 + 未成年
27         chi[i]= tmp1 + bir[i-3] + tmp2 ;//已成年+刚好成年+未成年
28         bir[i]= tmp1 + bir[i-3] ;//已成年+刚好成年
29 //以上文字表示的全是量,并不是意思。
30     }
31 
32 }
33 int main()
34 {
35     //freopen("input.txt", "r", stdin);
36     cal();
37     while(cin>>t,t)
38         cout<<num[t]<<endl;
39     return 0;
40 }
2048

 hdu 2044 一只小蜜蜂  完全是fabonacci

 1 #include <iostream>
 2 #include <map>
 3 #include <stack>
 4 #include <deque>
 5 #include <queue>
 6 #include <vector>
 7 #include <set>
 8 #include <algorithm>
 9 #include <cstring>
10 #include <cstdio>
11 
12 using namespace std;
13 const int N=51;
14 int t, tmp1, tmp2;
15 long long fab[N];
16 void cal()
17 {
18     fab[0]=fab[1]=1;
19     for(int i=2; i<N; i++)
20         fab[i]=fab[i-1]+fab[i-2];
21 
22 }
23 int main()
24 {
25     //freopen("input.txt", "r", stdin);
26     cal();
27     cin>>t;
28     while(t--)
29     {
30         cin>>tmp1>>tmp2;
31         cout<<fab[tmp2-tmp1]<<endl;
32     }
33 
34     return 0;
35 }
2044

 hdu 2050 折线分割平面  解法看此博客 http://blog.sina.com.cn/s/blog_76eabc150100swg8.html

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 const int N=10002;
 5 long long a[N];
 6 void cal()
 7 {
 8     a[0]=1;a[1]=2;a[2]=7;
 9     for(int i=3; i<N; i++)
10         a[i]=(4*i-3)+a[i-1];
11 }
12 int main()
13 {
14     //freopen("input.txt", "r", stdin);
15     cal();
16     int t, i;
17     cin>>t;
18     while(t--)
19     {
20         scanf("%d",&i);
21         printf("%d
",a[i]);
22     }
23     return 0;
24 }
HDU2050

 B.working out 用dp预处理4个角,再穷举除了边框外所有的格子,每格有两种可能,最后求出最大。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5 #define ll long long
  6 const int N=1002;
  7 long long a[N][N];
  8 
  9 struct pos
 10 {
 11     ll lef_top;
 12     ll rig_top;
 13     ll lef_bot;
 14     ll rig_bot;
 15 }dp[N][N];
 16 int n, m;
 17 
 18 void cal_dp()
 19 {
 20     //左上
 21     dp[0][0].lef_top=a[0][0];
 22     for(int i=1; i<m; i++)    dp[0][i].lef_top=dp[0][i-1].lef_top+a[0][i];
 23     for(int i=1; i<m; i++)    dp[i][0].lef_top=dp[i-1][0].lef_top+a[i][0];
 24     //左下
 25     dp[n-1][0].lef_bot=a[n-1][0];
 26     for(int i=1; i<m; i++)      dp[n-1][i].lef_bot=dp[n-1][i-1].lef_bot+a[n-1][i];
 27     for(int i=n-2; i>=0; i--)   dp[i][0].lef_bot=dp[i+1][0].lef_bot+a[i][0];
 28     //右上
 29     dp[0][m-1].rig_top=a[0][m-1];
 30     for(int i=m-2; i>=0; i--)   dp[0][i].rig_top=dp[0][i+1].rig_top+a[0][i];
 31     for(int i=1; i<n; i++)      dp[i][m-1].rig_top=dp[i-1][m-1].rig_top+a[i][m-1];
 32     //右下
 33     dp[n-1][m-1].rig_bot=a[n-1][m-1];
 34     for(int i=m-2; i>=0; i--)    dp[n-1][i].rig_bot=dp[n-1][i+1].rig_bot+a[n-1][i];
 35     for(int i=n-2; i>=0; i--)    dp[i][m-1].rig_bot=dp[i+1][m-1].rig_bot+a[i][m-1];
 36 
 37     for(int i=1; i<n; i++)  //左上
 38     {
 39         for(int j=1; j<m; j++)
 40         {
 41             dp[i][j].lef_top=max(dp[i][j-1].lef_top, dp[i-1][j].lef_top)+a[i][j];
 42         }
 43     }
 44 
 45     for(int i=n-2; i>=0; i--)  //左下
 46     {
 47         for(int j=1; j<m; j++)
 48         {
 49             dp[i][j].lef_bot=max(dp[i][j-1].lef_bot, dp[i+1][j].lef_bot)+a[i][j];
 50         }
 51     }
 52 
 53     for(int i=1; i<n; i++)      //右上
 54     {
 55         for(int j=m-2; j>=0; j--)
 56         {
 57             dp[i][j].rig_top=max(dp[i][j+1].rig_top, dp[i-1][j].rig_top)+a[i][j];
 58         }
 59     }
 60 
 61     for(int i=n-2; i>=0; i--)
 62     {
 63         for(int j=m-2; j>=0; j--)
 64         {
 65             dp[i][j].rig_bot=max(dp[i][j+1].rig_bot, dp[i+1][j].rig_bot)+a[i][j];
 66         }
 67     }
 68 
 69 }
 70 
 71 long long enu()
 72 {
 73     //对非外环的所有格子进行穷举
 74     long long ans=0;
 75     for(int i=1; i<n-1; i++)
 76     {
 77         for(int j=1; j<m-1; j++)
 78         {
 79             //左上:往右 左下:往上            //左上:往下 左下:往右
 80             long long tmp1=dp[i][j-1].lef_top+dp[i][j+1].rig_bot+dp[i+1][j].lef_bot+dp[i-1][j].rig_top;
 81             long long tmp2=dp[i-1][j].lef_top+dp[i+1][j].rig_bot+dp[i][j-1].lef_bot+dp[i][j+1].rig_top;
 82             //cout<<tmp1<<" "<<tmp2<<endl;
 83             if( ans<max(tmp1,tmp2) )
 84                 ans=tmp1>tmp2?tmp1:tmp2;
 85 
 86         }
 87     }
 88     return ans;
 89 }
 90 
 91 int main()
 92 {
 93     //freopen("input.txt", "r", stdin);
 94     while(cin>>n>>m)
 95     {
 96         memset(dp,0,sizeof(dp));
 97         for(int i=0; i<n; i++)
 98             for(int j=0; j<m; j++)
 99                 scanf("%d",&a[i][j]);
100         cal_dp();
101         cout<<enu()<<endl;;
102     }
103     return 0;
104 }
CF 429B

 UVA10328  Coin Toss  dp带限制的递推,大数

    +代码在此

HDU Number String  排列组合数问题,题解戳代码。题不错,技巧性很强。

    +代码在此

HDU The King’s Ups and Downs  排列组合数问题,题解戳代码

    +代码在此

二、背包专题

UVA-624 CD   要记录路径的常规01背包

    +代码在此

HDU 2955 Robberies 背包容量是double型,寻找其他背包容量。01背包变形。

    +代码在此

HDU 2602 Bone Collector  最常规的01背包。

    +代码在此

POJ 3624 Charm Bracelet  最常规的01背包。

    +代码在此

UVA 562 Dividing coins

    +代码在此

原文地址:https://www.cnblogs.com/xcw0754/p/4461072.html