标签:去掉 还需 排序 代码 names print 决定 ace ++
题意:给出n本书 每本书有高度和宽度,题意让我们先讲高度排序(保证每一本书的高度不同,从大从小排对答案不影响)
相邻的书的宽度差的绝对值为贡献,让我们去掉其中k本书,求最小贡献
思路:去掉书的想法很难实现,我们逆向思维,在其中增加n-k本书
那我们设定一个dp【i】【j】表示第i本书前面的所有书(包括第i本)选择j本情况下的最优值
那么答案就应该是从(n-k,n)选择一个最优值,因为我们是在某一本必选的情况下选择的最优
所以在不选这本的情况下可能不是最优,所以最后还需要再枚举一遍哪个最优
这是最后一部分,我们再来讲讲前面一部分
在枚举前i本书的情况下,我们再开一维来枚举前i本书放L本的情况
然后再枚举放L本时的最优值即可
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,k,m,Min=0x3f3f3f3f; 4 int f[501][501]; 5 //f[i][l]:以i作末尾,选了l本书时的最小花费 6 struct info 7 { 8 int h, w; 9 }a[1001]; 10 bool cmp(const info & x, const info & y) 11 { 12 return x.h < y.h; 13 } 14 int main() 15 { 16 cin>>n>>k; 17 m=n-k;//选取m本书 18 for(int i=1;i<=n;i++) 19 scanf("%d%d",&a[i].h,&a[i].w); 20 21 sort(a+1,a+n+1,cmp);//高度决定顺序 22 23 memset(f,20,sizeof(f));//初始极大,能缩小就缩小 24 for(int i=1;i<=n;i++) 25 f[i][1]=0; 26 //单独选择任何书都不会有花费 27 for(int i=2;i<=n;i++) 28 for(int l=2; l<=min(i,m);l++)//试着放第i本的时候 29 for(int j=1;j<=i-1;j++)//尝试与前面第j本相邻 30 //放下第i本时,能从之前长1的队列继承为长2的队列,也能从之前长2的队列继承为长3的队列……l表示放下后的长度 31 //显然试到第i本时,长度不会超过i,也不会超过m,m是最终需要的长度 32 if(j>=l-1) 33 f[i][l]=min(f[i][l],f[j][l-1]+abs(a[i].w-a[j].w/*这是尝试相邻的书本*/));//放第i本继承到长度为l,总花费越小越好 34 35 for(int i=m;i<=n;i++) 36 Min=min(Min,f[i][m]);//i的循环的意思是:以m结 尾的队列,可能最小,以m+1结尾的队列也可能的……以n结尾的队列也可能。 37 38 printf("%d\n",Min); 39 return 0; 40 }
标签:去掉 还需 排序 代码 names print 决定 ace ++
原文地址:https://www.cnblogs.com/pangbi/p/12557898.html