关于入门区间DP的递归算法与递推算法比较
第一次用博客,记录错题。
作为一个弱鸡,我认为递归算法比递推好写很多,递推的找条件简直变态,错一个就是0分,还是递归好用
例题: 石子合并:
递归算法:
#include<bits/stdc++.h>
using namespace std;
int n[255],dpmin[1500][1500],dpmax[1500][1500],sum[1500];
int dp_min(int l,int r)//l到r的数合并成一堆
{
if(dpmin[l][r]!=-1) return dpmin[l][r];
if(l==r)return 0;
int x=1e9;
for(int i=l;i<r;i++)
{
x=min(x,dp_min(l,i)+dp_min(i+1,r)+sum[r]-sum[l-1]);
}
return dpmin[l][r]=x;
}
int dp_max(int l,int r)//l到r的数合并成一堆
{
if(dpmax[l][r]!=-1) return dpmax[l][r];
if(l==r)return 0;
int x=-1e9;
for(int i=l;i<r;i++)
{
x=max(x,dp_max(l,i)+dp_max(i+1,r)+sum[r]-sum[l-1]);
}
return dpmax[l][r]=x;
}
int main()
{
memset(dpmin,-1,sizeof(dpmin));
memset(dpmax,-1,sizeof(dpmax));
int num;
scanf("%d",&num);
for(int i=1;i<=num;i++)
{
scanf("%d",&n[i]);
n[i+num]=n[i];
}
for(int i=1;i<=num+num;i++)
{
// dpmin[i][i]=n[i]; dpmax[i][i]=n[i];
sum[i]+=sum[i-1]+n[i];
}
int ans=0,ans2=1e9;
for(int i=1;i<=num;i++)
{
ans=max(ans,dp_max(i,i+num-1));
ans2=min(ans2,dp_min(i,i+num-1));
}
printf("%d\n%d",ans2,ans);
return 0;
}
数字游戏
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
int n,m,a[2005],sum[2005],mi[205][205][15],ma[205][205][15];
int read()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]=(a[i]%10+10)%10;//处理负数
a[i+n]=a[i];//建一个环
}
for(int i=1;i<=2*n;i++)
sum[i]=sum[i-1]+a[i];//前缀和
}
int dfs_min(int l,int r,int k)
{
if(mi[l][r][k]!=-1)return mi[l][r][k];//记忆化搜索
//当k==1时,即分好一个部分,用前缀和计算当前部分区间l-r的权值和
if(k==1)return mi[l][r][k]=(sum[r]-sum[l-1])%10;
int x=inf;
for(int i=l;i<r;i++)
{
if(i-l+1<k-1)continue;//无效状态
x=min(x,dfs_min(l,i,k-1)*dfs_min(i+1,r,1));//[l,i]分k-1份,[i+1,r]分1份
}
return mi[l][r][k]=x;
//记忆化+return
}
int dfs_max(int l,int r,int k)//代码理解同上,区别在于这是求 最大
{
if(ma[l][r][k]!=-1)return ma[l][r][k];
if(k==1)return ma[l][r][k]=(sum[r]-sum[l-1])%10;
int x=0;
for(int i=l;i<r;i++)
{
if(i-l+1<k-1)continue;//无效状态
x=max(x,dfs_max(l,i,k-1)*dfs_max(i+1,r,1));
}
return ma[l][r][k]=x;
}
void solve()
{
memset(mi,-1,sizeof(mi));
memset(ma,-1,sizeof(ma));
int maxx=-inf;
int minn=inf;
for(int i=1;i<=n;i++)
{
maxx=max(maxx,dfs_max(i,i+n-1,m));//在每一种方案下取最大
minn=min(minn,dfs_min(i,i+n-1,m));//在每一种方案下取最小
}
printf("%d\n%d\n",minn,maxx);
}
int main()
{
//freopen("in.txt","r",stdin);
read();
solve();
return 0;
}