ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

sdutoj 动态规划专题

2022-05-16 21:35:37  阅读:154  来源: 互联网

标签:std 专题 20 sdutoj int include 101 动态 dp


Overview | SDUT OnlineJudge

 

动态规划:

 

1.确定dp数组的含义

 

2.找到递推表达式

 

3.确定边界值,左边初始化,那一定左退右,上边初始化,一定上推下

 

 

 

动态规划是1生2,2生3的问题,后一个结果一定与前一个或前几个结果有关系

A - 递归的函数

最简单的形式,只是保存了历史记录

 1 #include<iostream>
 2 using namespace std;
 3 int p[21][21][21]={0};
 4 int f(int a,int b,int c)
 5 {
 6     if(a<=0||b<=0||c<=0)
 7         return 1;
 8     else if(a>20||b>20||c>20)
 9     {
10         if(p[20][20][20]==0)
11             p[20][20][20]=f(20,20,20);
12         return p[20][20][20];
13     }
14     else if(a<b&&b<c)
15     {
16         if(p[a][b][c]==0)
17             p[a][b][c]=f(a,b,c-1)+f(a,b-1,c-1)-f(a,b-1,c);
18         return p[a][b][c];
19     }
20     else
21     {
22         if(p[a][b][c]==0)
23             p[a][b][c]=f(a-1,b,c)+f(a-1,b-1,c)+f(a-1,b,c-1)-f(a-1,b-1,c-1);
24         return p[a][b][c];
25     }
26 }
27 int main()
28 {
29     int a,b,c;
30     while(cin>>a>>b>>c))
31        cout<<f(a,b,c)<<endl;
32     return 0;
33 }

B - 数字三角形问题(最简单的动态规划)

 

//动态规划解决问题的思路:

//大化小,把原本的多种情况,每次递减,最后汇总成只有一种情况

//动态规划:1.一定涉及到记录状态

//用一个数组进行记录

//         2.定义出记录数组的含义,比如这道题的含义是最大值

//         3.找到递推关系式,可以把大问题看成两步走的小问题,方便找关系

//         4.找起点并进行初始化,正方向和反方向都想一下 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n,a[101][101],dp[101][101];
 6     cin>>n;
 7     for(int i=1;i<=n;i++)
 8     {
 9         for(int j=1;j<=i;j++)
10         {
11             cin>>a[i][j];
12         }
13     }
14     for(int i=1;i<=n;i++)
15     dp[n][i]=a[n][i];
16     for(int i=n-1;i>=1;i--)
17     {
18         for(int j=1;j<=i;j++)
19         {
20             if(dp[i+1][j]>dp[i+1][j+1])
21             {
22                 dp[i][j]=dp[i+1][j]+a[i][j];
23             }
24             else
25             dp[i][j]=dp[i+1][j+1]+a[i][j];
26         }
27     }
28     cout<<dp[1][1]<<endl;
29     return 0;
30 }

C - 小鑫去爬山

//递归公式:未知的位置=已知的位置进行操作 

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n;
 6     int a[101][101],dp[101][101];
 7     while(cin>>n)
 8     {
 9         fill(a[0],a[0]+101*101,0);
10         fill(dp[0],dp[0]+101*101,0);
11         for(int i=1;i<=n;i++)
12         {
13             for(int j=1;j<=i;j++)
14             {
15                 cin>>a[i][j];
16             }
17         }
18         for(int i=1;i<=n;i++)
19         dp[n][i]=a[n][i];
20         for(int i=n-1;i>=1;i--)
21         {
22             for(int j=1;j<=n;j++)
23             {
24                 dp[i][j]=min(dp[i+1][j],dp[i+1][j+1])+a[i][j];
25             }
26         }
27         cout<<dp[1][1]<<endl;
28     }
29  } 

 

D - 最长公共子序列问题

//初始化了第0行和第0列(左边和上边)

//只能用已经有的求没有的,所以方向只能是左到右或者右到左

//ch1,ch2的下标0,实际上对应的是dp数组的下标1,i,j是dp的下标,i-1,j-1才是ch1,ch2的下标

//也是一个打表的过程,找出每一维的最大值,再更新下一个,有点像01背包

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int dp[501][501];
 4 int f(string ch1,string ch2)
 5 {
 6     int n=ch1.size();
 7     int m=ch2.size();
 8     for(int i=0;i<=n;i++)
 9     {
10         dp[i][0]=0;
11     }
12     for(int i=0;i<=m;i++)
13     {
14         dp[0][i]=0;
15     }
16     for(int i=1;i<=n;i++)
17     {
18         for(int j=1;j<=m;j++)
19         {
20             if(ch1[i-1]==ch2[j-1])
21             {
22                 dp[i][j]=dp[i-1][j-1]+1;
23             }
24             else
25             dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
26         }
27     }
28     return dp[n][m];
29 }
30 int main()
31 {
32     string ch1,ch2;
33     cin>>ch1>>ch2;
34     cout<<f(ch1,ch2)<<endl;
35     return 0;
36 }

 

E - 最长上升子序列

 

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[1010];
 4 int dp[1010];
 5 int main()
 6 {
 7     int n;
 8     int mx=0;
 9     cin>>n;
10     for(int i=1;i<=n;i++)
11     {
12         cin>>a[i];
13     }
14     for(int i=1;i<=n;i++)
15     {
16         dp[i]=1;
17         for(int j=1;j<=i;j++)
18         {
19             if(a[i]>a[j])
20             dp[i]=max(dp[i],dp[j]+1);
21         }
22         mx=max(dp[i],mx);
23     }
24     cout<<mx<<endl;
25     return 0;
26 }

F - 上升子序列

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int maxn=0;
 6     int n;
 7     int a[1010],dp[1010];
 8     cin>>n;
 9     for(int i=1;i<=n;i++)
10     {
11         cin>>a[i];
12     }
13     for(int i=1;i<=n;i++)
14     {
15         dp[i]=a[i];
16         for(int j=1;j<=i;j++)
17         {
18             if(a[i]>a[j])
19             {
20                 dp[i]=max(dp[i],dp[j]+a[i]);
21             }
22         }
23         maxn=max(dp[i],maxn);
24     }
25     cout<<maxn<<endl;
26     return 0;
27 }

H - 取数字问题

#include<bits/stdc++.h>
using namespace std;
int a[100][100];
int dp[100][100];
int main()
{
    int n,m;

    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            dp[i][j]=min(dp[i-1][j],dp[i][j-1])+a[i][j]; 
        }
    }
    if(dp[n][m]<=0)
    cout<<"-1"<<endl;
    else
    cout<<dp[n][m]<<endl;
    return 0;
}

I - 免费馅饼

//输入两个数据,大概率是二维

//后推前

//第一秒!=第零秒 ,注意边界!!! 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[100001][12];
 4 int main()
 5 {
 6     ios::sync_with_stdio(false);
 7     cin.tie(0);
 8     cout.tie(0);
 9     int n;
10     int x,t;
11     while(cin>>n,n)
12     {
13         int rant=0;
14         fill(a[0],a[0]+100001*12,0);
15         for(int i=0;i<n;i++)
16         {
17             cin>>x>>t;
18             a[t][x]++;
19             if(rant<t)
20             {
21                 rant=t;
22             }
23         }
24         for(int i=rant-1;i>=0;i--)
25         {
26             for(int j=0;j<=10;j++)
27             {
28                 if(j==0)
29                 {
30                     a[i][j]+=max(a[i+1][j],a[i+1][j+1]);
31                 }
32                 else
33                 {
34                     a[i][j]+=max(max(a[i+1][j-1],a[i+1][j]),a[i+1][j+1]);
35                 }
36             }
37         }
38         cout<<a[0][5]<<endl;
39     }
40     return 0;
41  } 

J - 走迷宫(dfs)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,b1,b2,e1,e2;
 4 int dit[4][2]={0,-1,-1,0,0,1,1,0};
 5 int a[30][30],b[100];
 6 int book[30][30];
 7 int flag=0;
 8 int ii=1;
 9 void dfs(int b1,int b2,int ii)
10 {
11     if(b1==e1&&b2==e2)
12     {
13         flag=1;
14         for(int i=1;i<=ii-2;i+=2)
15         {
16             cout<<"("<<b[i]<<","<<b[i+1]<<")";
17             if(i!=ii-2)
18             cout<<"->";
19         }
20         cout<<endl;
21         return;
22     }
23     for(int i=0;i<4;i++)
24     {
25         int x=b1+dit[i][0];
26         int y=b2+dit[i][1];
27         if(a[x][y]==0||book[x][y]==1)
28         continue;
29         book[x][y]=1;
30         b[ii]=x;
31         b[ii+1]=y;
32         dfs(x,y,ii+2);
33         book[x][y]=0;
34     }
35 }
36 int main()
37 {
38     while(scanf("%d %d",&n,&m) == 2)
39     {
40         for(int i=1;i<=n;i++)
41     {
42         for(int j=1;j<=m;j++)
43         {
44             cin>>a[i][j];
45         }
46     }
47     cin>>b1>>b2>>e1>>e2;
48     book[b1][b2]=1;
49     b[1]=b1;
50     b[2]=b2;
51     ii+=2;
52     dfs(b1,b1,ii);
53     if(!flag)
54     cout<<"-1"<<endl;
55     }
56     
57     return 0;
58 }

 

 

 

标签:std,专题,20,sdutoj,int,include,101,动态,dp
来源: https://www.cnblogs.com/inawaken/p/16278576.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有