目录
数字三角形模型
1015. 摘花生【简单的基本模型】
https://www.acwing.com/problem/content/1017/
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int t,n,m,f[N][N];
int main(void)
{
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>f[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) f[i][j]+=max(f[i-1][j],f[i][j-1]);
cout<<f[n][m]<<endl;
}
return 0;
}
1018. 最低通行费【简单】
https://www.acwing.com/problem/content/1020/
题目说必须(2n-1)
步,隐含的条件就是不会走回头路。
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int f[N][N],n;
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) cin>>f[i][j];
for(int i=1;i<=n;i++) f[1][i]+=f[1][i-1];
for(int i=1;i<=n;i++) f[i][1]+=f[i-1][1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) f[i][j]=min(f[i-1][j],f[i][j-1])+f[i][j];
cout<<f[n][n]<<endl;
return 0;
}
1027. 方格取数【一般 / 摘花生走两次】
https://www.acwing.com/problem/content/1029/
上图摘自:小呆呆大佬https://www.acwing.com/solution/content/7164/
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int f[N*2][N][N],w[N][N],n,x,y,c;
int main(void)
{
cin>>n;
while(cin>>x>>y>>c,x||y||c) w[x][y]=c;
for(int k=2;k<=n+n;k++)
{
for(int i1=1;i1<=n;i1++)
{
for(int i2=1;i2<=n;i2++)
{
int j1=k-i1,j2=k-i2;
if(j1>=1&&j1<=n&&j2>=1&&j2<=n)
{
int t=w[i1][j1];
if(i1!=i2) t+=w[i2][j2];//不重合
int temp=f[k][i1][i2];
temp=max(temp,f[k-1][i1-1][i2-1]+t);
temp=max(temp,f[k-1][i1-1][i2]+t);
temp=max(temp,f[k-1][i1][i2-1]+t);
temp=max(temp,f[k-1][i1][i2]+t);
f[k][i1][i2]=temp;
}
}
}
}
cout<<f[n*2][n][n]<<endl;
return 0;
}
最长上升子序列模型【LIS】
1017. 怪盗基德的滑翔翼【简单模型】
https://www.acwing.com/problem/content/1019/
正着跑一遍,反着跑一遍,取一个max即可。
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int t,n,a[N],f[N];
int main(void)
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int res=0;
for(int i=1;i<=n;i++)
{
f[i]=1;
for(int j=1;j<i;j++) if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
res=max(res,f[i]);
}
for(int i=n;i>=1;i--)
{
f[i]=1;
for(int j=n;j>i;j--) if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);
res=max(res,f[i]);
}
cout<<res<<endl;
}
return 0;
}
1014. 登山【简单扩展】
https://www.acwing.com/problem/content/1016/
正着跑一次,反着跑一次。
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int f1[N],f2[N],h[N],ans,n;
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>h[i];
for(int i=1;i<=n;i++)
{
f1[i]=1;
for(int j=1;j<i;j++) if(h[j]<h[i]) f1[i]=max(f1[i],f1[j]+1);
ans=max(ans,f1[i]);
}
for(int i=n;i>=1;i--)
{
f2[i]=1;
for(int j=n;j>i;j--) if(h[i]>h[j]) f2[i]=max(f2[i],f2[j]+1);
ans=max(ans,f1[i]+f2[i]-1);
}
cout<<ans;
return 0;
}
482. 合唱队形【简单扩展】
https://www.acwing.com/problem/content/484/
跟登山问题几乎一样,不过是对立的问题。
#include<bits/stdc++.h>
using namespace std;
const int N=250;
int f1[N],f2[N],h[N],n,ans;
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>h[i];
for(int i=1;i<=n;i++)
{
f1[i]=1;
for(int j=1;j<i;j++) if(h[i]>h[j]) f1[i]=max(f1[i],f1[j]+1);
}
for(int i=n;i>=1;i--)
{
f2[i]=1;
for(int j=n;j>i;j--) if(h[i]>h[j]) f2[i]=max(f2[i],f2[j]+1);
ans=max(ans,f1[i]+f2[i]-1);
}
cout<<n-ans<<endl;
return 0;
}