0
点赞
收藏
分享

微信扫一扫

kuangbin专题十二 基础DP

佃成成成成 2022-03-12 阅读 29

kuangbin专题十二 基础DP

A - HDU1024 Max Sum Plus PlusA - HDU1024 Max Sum Plus Plus

code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e6+10,inf=0x3f3f3f3f;
int pre[N],f[N],a[N],m,n;

int main()
{
	while(~scanf("%d %d",&m,&n))
	{
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		
		memset(pre,0,sizeof(pre));
		memset(f,0,sizeof(f));
		int Max;
		for(int i=1;i<=m;i++)
		{
			Max=-inf;
			for(int j=i;j<=n;j++)
			{
				f[j]=max(f[j-1],pre[j-1])+a[j];
				pre[j-1]=Max;
				Max=max(Max,f[j]);
			}
		}
		printf("%d\n",Max);
	}
	return 0;
}

题意

思路

B - HDU1029 Ignatius and the Princess IV

code:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=1e6+10; 
int n,a[N];
int main()
{
	while(cin>>n)
	{
		memset(a,0,sizeof(a));
		int flag=0;
		for(int i=1;i<=n;i++)
		{
			int c;
			cin>>c;
			a[c]++;
			if(a[c]>=((n+1)/2)&&flag==0) {
				cout<<c<<"\n";
				flag=1;
				continue;
			}
		}
	}
	return 0;
}

水题,不过多解释。

C - HDU1069 Monkey and Banana

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=200;
struct Node{
	int x,y,z;
}block[200];
int t,n,f[N];
bool cmp(Node a,Node b)
{
	if(a.x!=b.x) return a.x<b.x;
	else return a.y<b.y;
}
int main()
{
	t=1;
	while(cin>>n)
	{
		if(n==0) break;
		
		for(int i=0;i<n;i++)
		{
			int a,b,c;
			cin>>a>>b>>c;
			block[6*i].x=a,block[6*i].y=b,block[6*i].z=c;
			block[6*i+1].x=a,block[6*i+1].y=c,block[6*i+1].z=b;
			block[6*i+2].x=b,block[6*i+2].y=a,block[6*i+2].z=c;
			block[6*i+3].x=b,block[6*i+3].y=c,block[6*i+3].z=a;
			block[6*i+4].x=c,block[6*i+4].y=a,block[6*i+4].z=b;
			block[6*i+5].x=c,block[6*i+5].y=b,block[6*i+5].z=a;
		}
		sort(block,block+6*n,cmp);
		for(int i=0;i<6*n;i++)
		{
			f[i]=block[i].z;
			for(int j=0;j<i;j++)
			{
				if(block[i].x>block[j].x&&block[i].y>block[j].y)
				f[i]=max(f[i],f[j]+block[i].z);	
			}
		}
		int maxn=-1;
		for(int i=0;i<6*n;i++)
		{
			if(maxn<f[i])
			maxn=f[i];
		}
		printf("Case %d: maximum height = %d\n",t++,maxn);
	}
	return 0;
}

题意

思路

D - HDU1074 Doing Homework

code:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=20,inf=0x3f3f3f3f;
struct Node{
	string name;
	int deadline;
	int day;
}course[N];
struct Dp{
	int now;
	int pre;
	int score;
}dp[1 << N];
void output(int x)
{
	int l=0;
	int ans[N];
	while(x)
	{
		ans[l++]=dp[x].pre;
		x=x-(1 << dp[x].pre);
	}
	for(int i=l-1;i>=0;i--)
	cout<<course[ans[i]].name<<"\n";
}
int main()
{
	int t,n;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=0;i<n;i++)
		{
			cin >> course[i].name >> course[i].deadline >> course[i].day;
		}
		dp[0].now=0;
		dp[0].pre=-1;
		dp[0].score=0;
		for(int i=1;i<(1 << n);i++)
		dp[i].score = inf;
		for(int i=0;i<(1 << n);i++)
		{
			for(int j=0;j<=n-1;j++)
			{
				int tmp=(1 << j);
				if(i & tmp) continue;
				int t=i | tmp;
				int time=dp[i].now+course[j].day;
				int sc=0;
				if(time>course[j].deadline)
				sc=time-course[j].deadline;
				sc+=dp[i].score;
				if(dp[t].score>sc)
				{
					dp[t].now=time;
					dp[t].pre=j;
					dp[t].score=sc;
				}
			}
		}
		cout<<dp[(1 << n)-1].score<<"\n";
		output((1 << n)-1);
	}
	return 0;
}

题意

思路

E - Hdu1087 Super Jumping! Jumping! Jumping!

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1005;
ll ans,dp[N],a[N],n;
int main()
{
	while(cin>>n)
	{
		if(n==0) break;
		for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
		ans=-1;
		for(int i=1;i<=n;i++)
		{
			dp[i]=a[i];
			for(int j=1;j<=i;j++)
			{
				if(a[i]>a[j])
				{
					dp[i]=max(dp[j]+a[i],dp[i]);
				}
			}
			ans=max(ans,dp[i]);
		}
		cout<<ans<<"\n";
	}
	
	return 0;
}

题意

思路

F - Hdu1114 Piggy-Bank

code:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int t;
int e,f,n,v[505],w[505],dp[10005];
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		cin>>e>>f>>n;
		for(int i=1;i<=n;i++)
		scanf("%d %d",&v[i],&w[i]);
		
		dp[0]=0;
		for(int i=1;i<=f-e;i++) dp[i]=0x3f3f3f3f;
		
		for(int i=1;i<=n;i++)
    	for(int j=w[i];j<=f-e;j++)
    	{
        	dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
    	}
    	if(dp[f-e]!=0x3f3f3f3f)
    	cout<<"The minimum amount of money in the piggy-bank is "<<dp[f-e]<<"."<<endl;
    	else cout<<"This is impossible."<<endl;
	}
	return 0;
}

题意

思路

G - HDU1176 免费馅饼

code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,dp[100005][20];
int main()
{
	while(~scanf("%d",&n))
	{
		if(n==0) break;
		int maxt=-1;
		memset(dp,0,sizeof(dp));
		for(int i=0;i<n;i++)
		{
			int t,p;
			scanf("%d%d",&p,&t);
			dp[t][p]++;
			maxt=max(maxt,t);
		}
		for(int i=maxt;i>=0;i--)
		{
			for(int j=0;j<11;j++)
			{
				dp[i][j]+=max(dp[i+1][j],max(dp[i+1][j-1],dp[i+1][j+1]));
			}
		}
		printf("%d\n",dp[0][5]);
	}
	return 0;
}

题意

思路

H - HDU1260 Tickets

code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=2005;
int s[N],d[N],dp[N];
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		int k;
		cin>>k;
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=k;i++)
		cin>>s[i];
		for(int i=2;i<=k;i++)
		cin>>d[i];
		d[1]=s[1];
		for(int i=2;i<=k;i++)
		{
			dp[i]=min(dp[i-1]+s[i],dp[i-2]+d[i]);
		}
		int ss=d[k]%60;
		int m=d[k]/60%60;
		int h=d[k]/3600;
		h+=8;
		if(h<=12)
		printf("%02d:%02d:%02d am\n",h,m,ss);
		else printf("%02d:%02d:%02d pm\n",h-12,m,ss);
		
	}
	return 0;
}

题意

思路

I - Hdu1257 最少拦截系统

code:

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int a[N],dp[N];
int main()
{
	int n;
	while(cin>>n)
	{
		for(int i=0;i<n;i++) {
			cin>>a[i];
			dp[i]=1;
		}
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<i;j++)
			{
				if(a[j]<a[i])
				{
					dp[i]=max(dp[i],dp[j]+1); 
				}
			}
		}
		int ans=0;
		for(int i=0;i<n;i++)
		ans=max(ans,dp[i]);
		cout<<ans<<"\n";
	}
	return 0;
}

题意

思路

J - HDU1160 FatMouse’s Speed

code:

#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N=1e3+10;
struct Node{
	int w;
	int c;
	int id;
}node[N];
struct Dp{
	int num;
	int pre;
}dp[N];
void Pri_path(int x){
    if(dp[x].pre != -1){
        Pri_path(dp[x].pre);
    }
    printf("%d\n",x);
}
bool cmp(Node a,Node b)
{
	if(a.c!=b.c) return a.c>b.c;
}
int main()
{
	int t=1;
	while(~scanf("%d %d",&node[t].w,&node[t].c))
	{
		node[t].id = t;
		++t;
	}
	sort(node+1,node+t+1,cmp);
	for(int i=1;i<=t;i++)
	dp[i].num=1,dp[i].pre=-1;
	
	int ans=0,x=-1;
	for(int i=1;i<=t;i++)
	{
		int mav=0,v=-1;
		for(int j = 1; j < i; j++){
            if(node[j].w < node[i].w && node[j].c > node[i].c && dp[j].num > mav){
                mav = dp[j].num, v = j;
            }
        }
        dp[i].num = mav + 1;
        dp[i].pre = v;
        if(dp[i].num > ans){
            ans = dp[i].num, x = i;
        }
	}
	printf("%d\n", ans);
    Pri_path(x);
	return 0;
}

题意

思路

K - POJ1015 Jury Compromise

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
int dp[21][805];
//现用dp(j, k)表示,取j 个候选人,使其辩控差为k 的所有方案中,
//辩控和最大的那个方案(该方案称为“方案f(j, k)”)的辩控和
vector<int> path[21][805];//记录路径  path[i][j] 取i个人  他们的差为j时候的路径
int main()
{
	int n,m,t=1;
	while(~scanf("%d %d",&n,&m))
	{
		if(n==0&&m==0) break;
		int sub[210],_plus[210];
		for(int i=0;i<n;i++)
		{
			int d,p;
			scanf("%d %d",&d,&p);
			sub[i]=d-p;
			_plus[i]=d+p;
		}
		for(int i=0;i<m;i++)
		{
			for(int j=0;j<805;j++)
			{
				path[i][j].clear();
			}
		}
		memset(dp,-1,sizeof(dp));
		int fix=20*m;
		dp[0][fix]=0;
		for(int k=0;k<n;k++)
		{
			for(int i=m-1;i>=0;i--)
			{
				for(int j=0;j<2*fix;j++)
				{
					if(dp[i][j]>=0)
					{
						if((dp[i+1][j+sub[k]])<=(dp[i][j]+_plus[k]))
						{
							dp[i+1][j+sub[k]]=dp[i][j]+_plus[k];
							path[i+1][j+sub[k]]=path[i][j];
							path[i+1][j+sub[k]].push_back(k);
						}
					}
				}
			}
		}
		int i;
		for(i=0;dp[m][fix+i]==-1&&dp[m][fix-i]==-1;i++);
		int temp = (dp[m][fix+i] > dp[m][fix-i]) ? i : -i;
		
		int sumD=(dp[m][fix+temp]+temp)/2;
		int sumP=(dp[m][fix+temp]-temp)/2;
		
		printf("Jury #%d\n",t++);
		printf("Best jury has value %d for prosecution and value %d for defence:\n",sumD,sumP);
		for(int i=0;i<m;i++)
		printf(" %d",path[m][fix+temp][i]+1);
		printf("\n\n");
	}
	return 0;
}

题意

思路

L - POJ1458 Common Subsequence

code:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=1e3+10;
int dp[N][N];
int main()
{
	char a[N],b[N];
	while(~scanf("%s %s",a,b))
	{
		int n=strlen(a);
		int m=strlen(b);
		memset(dp,0,sizeof(dp));
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				if(a[i]==b[j])
				dp[i+1][j+1]=dp[i][j]+1;
				else dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
			}
		}
		printf("%d\n",dp[n][m]);
	}
	return 0;
}

题意:给定两个序列,求最长公共子序列的长度。

思路:经典LCS模板题。

M - POJ1661 Help Jimmy

code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1005,INF=0x3f3f3f3f;
int dp[N][5];
int n,x,y,Max;
struct Plat{
	int x1,x2,high;
}plat[N];

bool cmp(Plat a,Plat b)
{
	return a.high<b.high;
}


void LeftMove(int i)
{
	int k=i-1;
	while((k>0)&&(plat[i].high-plat[k].high<=Max))
	{
		if((plat[i].x1>=plat[k].x1)&&(plat[i].x1<=plat[k].x2))
		{
			dp[i][0]=plat[i].high-plat[k].high+min(plat[i].x1-plat[k].x1+dp[k][0],plat[k].x2-plat[i].x1+dp[k][1]);
			return;
		}
		else --k;
		
	}
	if(plat[i].high-plat[k].high>Max)
	dp[i][0]=INF;
	else dp[i][0]=plat[i].high;
}
void RightMove(int i)
{
	int k=i-1;
	while((k>0)&&(plat[i].high-plat[k].high<=Max))
	{
		if((plat[i].x2>=plat[k].x1)&&(plat[i].x2<=plat[k].x2))
		{
			dp[i][1]=plat[i].high-plat[k].high+min(plat[i].x2-plat[k].x1+dp[k][0],plat[k].x2-plat[i].x2+dp[k][1]);
			return;
		}
		else --k;
		
	}
	if(plat[i].high-plat[k].high>Max)
	dp[i][1]=INF;
	else dp[i][1]=plat[i].high;
}
int ShortestTime()
{
	for(int i=1;i<=n+1;i++)
	{
		LeftMove(i);
		RightMove(i);
	}
	return min(dp[n+1][0],dp[n+1][1]);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		
		scanf("%d%d%d%d",&n,&x,&y,&Max);
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d%d",&plat[i].x1,&plat[i].x2,&plat[i].high);
		}
		plat[n+1].x1=x;
		plat[n+1].x2=x;
		plat[n+1].high=y;
		plat[0].x1=-20000;
		plat[0].x2=20000;
		plat[0].high=0;
		sort(plat,plat+n+2,cmp);
		printf("%d\n",ShortestTime());
	}
	return 0;
}

题意

思路

N - POJ2533 Longest Ordered Subsequence

code:

#include<iostream>
#include<algorithm>
using namespace std;
int dp[1005],a[1005];
int main()
{
	int n,ans=-1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;i++)
	{
		dp[i]=1;
		for(int j=1;j<i;j++)
		{
			if(a[i]>a[j])
			{
				dp[i]=max(dp[i],dp[j]+1);
			}
		}
		ans=max(ans,dp[i]);
	}
	printf("%d",ans);
	return 0;
}

题意:给出n个数,求最长上升子序列的数量。

思路:经典LIS模板题。

O - POJ3186 Treats for the Cows

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2005;
int a[N],dp[N][N];

int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	for(int len=1;len<=n;len++)
	{
		for(int i=1,j=i+len-1;i<=n;i++,j++)
		{
			dp[i][j]=max(dp[i+1][j]+a[i]*(n-len+1),dp[i][j-1]+a[j]*(n-len+1));
		}
	}
	printf("%d",dp[1][n]);
	return 0;
}

题意:双端队列里取数,每次取数都乘上它取出时的序列号,问和最大为多少。

思路:dp[i][j]表示序列从i~j的所求值。经典区间DP,不过是倒着推,难点在于当前区间天数的表示。

P - HDU1078 FatMouse and Cheese

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int a[105][105];
bool vis[105][105];
int ans[105][105],dx[]={1,-1,0,0},dy[]={0,0,1,-1};
int n,k;
void dfs(int x,int y)
{
	
	for(int i=0;i<4;i++)
	{
		for(int j=1;j<=k;j++)
		{
			int xx=x+dx[i]*j;
			int yy=y+dy[i]*j;
			if(a[x][y]<a[xx][yy]&&vis[xx][yy]==0&&xx>=0&&xx<n&&yy>=0&&yy<n)
			{
				vis[xx][yy]=1;
				ans[xx][yy]=max(ans[xx][yy],ans[x][y]+a[xx][yy]);
				dfs(xx,yy);
				vis[xx][yy]=0;
			}
		}
	}
}
int main()
{
	
	while(~scanf("%d%d",&n,&k))
	{
		if(n==-1&&k==-1) return 0;
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
			{
				scanf("%d",&a[i][j]);
				ans[i][j]=a[i][j];
			}
		
		dfs(0,0);
		int anss=-1;
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
			{
				anss=max(anss,ans[i][j]);
			}
		printf("%d\n",anss);
	}
	return 0;
}

题意:老鼠一开始在(0,0)的位置,每个位置都有一定数量的食物,老鼠一次最多走k步,规定走过的位置的食物量要越来越大,问老鼠最多能吃的食物量。

思路:挺简单的,记忆化搜索DP。

Q - HDU285 Phalanx

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1005;
char st[maxn][maxn];
int dp[maxn][maxn];
int main()
{
	int n,ans,t1,t2;
	while(scanf("%d",&n) && n)
	{
		ans=0;
		for(int i=0;i<n;i++)
		scanf("%s",st[i]);
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(i==0||j==n-1)
				dp[i][j]=1;
				else{
					t1=i,t2=j;
					while(t1>=0&&t2<n)
					{
						if(st[t1][j]==st[i][t2])
						t1--,t2++;
						else break;
					}
					int t=i-t1;
					dp[i][j] = min(i-t1, dp[i-1][j+1]+1);
				}
				ans=max(ans,dp[i][j]);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

题意:给定一个n行n列的字符矩阵。求这个矩阵的最大对称子矩阵的大小。在这里的对称指的是关于左下和右上相连的对角线对称。

思路:我们定义dp[i][j]:0~i, j~n-1形成的矩阵的最大对称子矩阵的大小。
在这里插入图片描述
我们可以先将dp[i][j]全部初始化为1,也可以像上面代码一样只初始化第一行和第n-1列为1,后面的具体操作可结合代码和图片来理解。

R - POJ3616 Milking Time

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Node{
	int l,r,e;
}a[1005];
int f[1005];
bool cmp(Node a,Node b)
{
	return a.r<b.r;
}
int main()
{
	int N,M,R;
	scanf("%d%d%d",&N,&M,&R);
	for(int i=0;i<M;i++)
	{
		scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].e);
		a[i].r+=R;//预处理
	}
	sort(a,a+M,cmp);//按右端点从小到大排序
	int k;
	k=0;
	for(int i=1;i<=N+R;i++)
	{
		f[i]=f[i-1];
		while(a[k].r==i) f[i]=max(f[i],f[a[k].l]+a[k++].e);//可能有多个值相等,要用while
	}
	printf("%d",f[N+R]);
	return 0;
}

题意:给了M个时间段和产奶量,要在规定的N个小时内分配合理时间使总产奶量最大。注意奶牛产完奶后要有R个小时休息后才能继续工作。

思路:见代码和注释。

S - POJ3666 Making the Grade

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2005,INF=0x3f3f3f3f;
int dp[N][N],a[N],b[N],n;
void solve()
{
	for(int i=1;i<=n;i++)
	{
		int minn=INF;
		for(int j=1;j<=n;j++)
		{
			int cost=abs(a[i]-b[j]);
			minn=min(minn,dp[i-1][j]);//dp[i-1][j]指的是前i-1个数最大值为b[j]时的最小代价
			dp[i][j]=cost+minn;
		}
	}
	int ans=INF;
	for(int i=1;i<=n;i++)
	ans=min(ans,dp[n][i]);
	printf("%d",ans);
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+1+n);
	solve();
	
	return 0;
}

这道题一开始我没啥思路,后来看了题解才知道是线性DP+离散化。可以参考这位博主的思路。

题意:给出一个长度为 n 的序列,要求使序列变为非递增或非递减序列,问花费的最少代价。在之后的做题中统一将其改为非递减序列。原因后面会解释。

思路:题目显然是 LIS 问题的变种,线性 DP 无疑

对于长度为 i 的序列,其最优解只与两个值有关,一个是这个序列处理的代价,另一个则是这个序列处理后的尾部的值。那么显然,我们希望序列处理的代价越小越好,而序列处理后的尾部的值越小越好,因为当序列处理完毕后,尾部的值是这个序列的最大值,其值越小,第 i+1 个数不花任何代价直接接在其后面的可能性就更大。

设 dp[i][j] 为长度为前 i 个数构成的序列,且处理完最大值为 j 所花费的相应代价,那么可以得出状态转移方程:

dp[i][j]=abs(j-a[i])+min(dp[i-1][k]),k<=j,其中 abs(j-a[i]) 代表处理的代价,min(dp[i-1][k]) 代表前 i-1 个数构成的序列最大值为 k 时所花费的最小代价

注意到 j 最大可达到 1,000,000,000,那么显然枚举的话一定会 TLE,而 n 的大小最大只有 2000,那么使用离散化的思想,先对序列 a[i] 进行处理,即:

对于长度为 n 的序列,可以发现序列中的某个数 a[i],无论怎么变化,最小代价一定是序列中的某个数与当前这个数 a[i] 的差,因此我们可以建立一个备份数组 b[i],将原来的 j-a[i] 转变为 b[j]-a[i],也即 abs(b[j]-a[i]),然后再进行动态规划

最后,再从 dp[n][1~n] 中寻找最小值即可。

有几点我的看法:

1.我感觉博主原代码中的注释有点问题,所以代码我改了一下,dp[i][j]在离散化之后的意义就变了,变为前i个数最大值为b[j]时的最小代价
2.解释下为什么统一将序列改为非递减,我认为在原文中他有两个方向可以走,你从左边开始走序列为非递减,那么你从右边开始走序列就为非递增,所以我们可以统一将序列改为非递减。
3.为什么对于长度为 n 的序列,可以发现序列中的某个数 a[i],无论怎么变化,最小代价一定是序列中的某个数与当前这个数 a[i] 的差?这点很好解释,当你要改变当前的值时,你所替换的值要么是与前一个改变后的值相等,要么与后一个未改变的值相等,毕竟是要使尾部的值越小越好,这样改动才能使和最小。

举报

相关推荐

0 条评论