算法复习(四五六)
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法复习(四五六)相关的知识,希望对你有一定的参考价值。
动态规划
动态规划算法的有效性依赖于问题本身所具有的两个重要性质:最优子结构、重叠子问题
关于动态规划算法和备忘录方法的适用条件:
要求:
用分治法和动态规划法分别解决最大子段和问题(第四步求最优解不需要掌握)
掌握用动态规划法解决0-1背包问题
最长单调递增子序列
最长公共子序列(会写出计算最长公共子序列长度的递推式即可)
矩阵连乘问题
备忘录做法:
signed main()
cin>>n;
for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dp[i][j]=inf;
for(int i=1;i<=n;i++) dp[i][i]=0;
for(int i=1;i<=n;i++)
cin>>row[i]>>col[i];
for(int i=1;i<=n;i++) p[i]=col[i];
p[0]=row[1];
for(int len=2;len<=n;len++)
for(int i=1;i<=n-len+1;i++)
int j=i+len-1;
dp[i][j]=dp[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(int k=i+1;k<j;k++)
int tmp=dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j];
if(tmp<dp[i][j])
dp[i][j]=tmp;
s[i][j]=k;
cout<<dp[1][n]<<endl;
dfs(1,n);
return 0;
动态规划做法:
signed main()
cin>>n;
for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dp[i][j]=inf;
for(int i=1;i<=n;i++) dp[i][i]=0;
for(int i=1;i<=n;i++)
cin>>row[i]>>col[i];
for(int i=1;i<=n;i++) p[i]=col[i];
p[0]=row[1];
for(int len=2;len<=n;len++)
for(int i=1;i<=n-len+1;i++)
int j=i+len-1;
dp[i][j]=dp[i][i]+dp[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(int k=i+1;k<j;k++)
if(dp[i][j]>dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j])
dp[i][j]=dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j];
s[i][j]=k;
cout<<dp[1][n]<<endl;
print(1,n);
return 0;
最大子段和问题
法一:
#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
using namespace std;
const int N=1e3+5;
const int inf=1e18;
int n,a[N],dp[N];
signed main()
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int ans=0;
for(int i=1;i<=n;i++)
dp[i]=max(dp[i-1]+a[i],0ll);
ans=max(ans,dp[i]);
cout<<ans<<endl;
return 0;
/*
7
-2 11 -4 13 -5 -2 -100
*/
法二:
signed main()
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int ans=0,b=0;
for(int i=1;i<=n;i++)
if(b>0)
b+=a[i];
else
b=a[i];
ans=max(ans,b);
cout<<ans<<endl;
return 0;
法三:
#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
using namespace std;
const int N=1e3+5;
const int inf=1e18;
int n,a[N],dp[N];
int dfs(int l,int r)
if(l==r)
return a[l]>0?a[l]:0;
int sum=0,mid=(l+r)/2;
int left=dfs(l,mid);
int right=dfs(mid+1,r);
int s1=0,s2=0,tmp=0;
for(int i=mid;i>=l;i--)
tmp+=a[i];
if(s1<tmp) s1=tmp;
tmp=0;
for(int i=mid+1;i<=r;i++)
tmp+=a[i];
if(s2<tmp) s2=tmp;
sum=s1+s2;
if(left>sum) sum=left;
if(right>sum) sum=right;
return sum;
signed main()
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cout<<dfs(1,n)<<endl;
return 0;
/*
7
-2 11 -4 13 -5 -2 100
*/
01背包问题
int n,m,f[105][N],dp[N];
void fun1()
for(int i=1;i<=n;i++) //物品i
for(int j=1;j<=m;j++) //容量j
if(j<w[i])
f[i][j]=f[i-1][j];
else
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i]);
cout<<f[n][m]<<endl;
void fun2() //逆序更新
for(int i=1;i<=n;i++)
for(int j=m;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+c[i]);
最长单调递增子序列
for(int i=1;i<=n;i++) cin>>a[i],dp[i]=1;
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)
if(a[j]<=a[i])
dp[i]=max(dp[i],dp[j]+1);
cout<<dp[n]<<endl;
最长公共子序列
cin>>s1>>s2;
len1=s1.length(),len2=s2.length();
s1=" "+s1,s2=" "+s2;
for(int i=1;i<=len1;i++)
for(int j=1;j<=len2;j++)
if(s1[i]==s2[j]) dp[i][j]=dp[i-1][j-1]+1,s[i][j]=1;
else
if(dp[i-1][j]>dp[i][j-1])
dp[i][j]=dp[i-1][j];s[i][j]=2;//上面
else
dp[i][j]=dp[i][j-1];s[i][j]=3;
cout<<dp[len1][len2]<<endl;
return 0;
贪心算法
适合于贪心算法求解的问题具有:贪心选择性质、最优子结构性质
贪心算法可以获取到问题的局部最优解,不一定能获取到全局最优解
掌握使用贪心算法解决:活动安排问题、背包问题、最优装载问题(件数最多)、删数问题
活动安排问题
按照结束时间进行排序
int n,p[N];
struct node
int st,ed,id;
a[N];
bool cmp(node a,node b)
return a.ed<b.ed;
signed main()
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i].st>>a[i].ed;
a[i].id=i;
sort(a+1,a+n+1,cmp);
p[1]=1;
int ans=1,tmp=a[1].ed;
for(int i=2;i<=n;i++)
if(a[i].st>=tmp)
tmp=a[i].ed;ans++;
p[i]=1;
cout<<ans<<endl;
return 0;
背包问题
int n,p[N];
struct node
int w,v;
double d;
a[N];
bool cmp(node a,node b)
return a.d>b.d;
signed main()
cin>>n>>c;
for(int i=1;i<=n;i++)
cin>>a[i].w>>a[i].v;
a[i].d=a[i].v/a[i].w;
sort(a+1,a+n+1,cmp);
int i=1;
double ans=0;
while(i<=n&&a[i].w<=c)
c-=a[i].w;ans+=a[i].v;
i++;
if(i<=n) ans+=c*a[i].d;
cout<<ans<<endl;
return 0;
最优装载问题(件数最多)
重量轻的先装,找找重量从小到大进行排序
删数问题
找到最近下降点
#include <bits/stdc++.h>
#define int long long
using namespace std;
const 深度优先搜索算法解释下?