P1103 书本整理 - 洛谷
一、题目信息
1、题目链接:P1103 书本整理 - 洛谷。没有什么特别的思路,只是想记录下解这道题的曲折。
二、解题过程
1、状态转移方程,d[i][j]:表示前i本书留j本,不反映第i本书的去留情况,于是要有额外的空间存储d[i][j]对应的留下的最后一本书的序号pre。然后有以下情况:
- i = j 时:第i本书保留,此时d[i][j]=d[i-1][j-1]+width_dif(i,i-1)。width_dif(i,i-1)表示第i本书和第i-1本书的宽度差的绝对值,下同
- i > j 时,有两种情况:
- 保留第i本书,则此时d[i][j]=d[i-1][j-1]+width_dif(i,pre),pre是d[i-1][j-1]对应的留下的最后一本书的序号
- 不保留第i本书,则此时d[i][j]=d[i-1][j]
对于i>j,我们根据哪种情况得到的d[i][j]更小我们就选择哪种情况。然而若保留和不保留计算得到的d[i][j]相等呢,此时保留还是不保留呢?显然不能任意,于是我傻掉了。
2、于是只好乖乖的按照题解的做法,d[i][j]:表示前i本书留j本且第i本书留下,从而此时计算d[i][j]要考虑当前最后一本书的所有可能,变为d[i][j]=min{d[j-1][j-1]+width_dif(i,j-1), d[j][j-1]+width_dif(i,j), ..., d[i-1][j-1]+width_dif(i,i-1)},每一项分别对应最后一本书是第j-1本、第j本、...、第i-1本的情况。
3、这样这道题就结束了,动态规划边界就不写出来了
三、代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;bool compare(const vector<int> &v1,const vector<int> &v2){return v1[0]<v2[0];
}int main(){int n,k;cin>>n>>k;k=n-k;vector<vector<int>> arr(n+1,vector<int>(2));int h,w;for(int i=1;i<=n;i++){cin>>h>>w;arr[i][0]=h;arr[i][1]=w;}sort(arr.begin(),arr.end(),compare);int dp[n+1][k+1];for(int i=0;i<=n;i++){for(int j=0;j<=k;j++) dp[i][j]=0;}for(int i=2;i<=n;i++){for(int j=2;j<=i&&j<=k;j++){int min_result=20000;for(int m=j-1;m<=i-1;m++){int temp=dp[m][j-1]+abs(arr[i][1]-arr[m][1]);if(min_result>temp) min_result=temp;}dp[i][j]=min_result;}}int result=20000;for(int i=k;i<=n;i++){if(result>dp[i][k]) result=dp[i][k];}cout<<result;return 0;
}