UVALive - 6434 Number Assignment
分析:由题,我们需要决定新的容器放置的位置。
可以采用dp的方法
dp[j][i]代表到第j个数第i个容器的最优情况
对于dp[j][i]尝试在可能每个地方放置的新容器找最小值
状态转移方程 dp[j][i]=min(dp[j][i],dp[j-k][i-1]+a[j]-a[j-k+1]);
代码如下
#include <cstdio> #include <iostream> #include <algorithm> #include <stack> #include <cstring> using namespace std; #define INF 0x7fffffff typedef long long ll; ll c[110]; ll a[110]; ll dp[110][110]; int main() { std::ios::sync_with_stdio(false); int t,n,m,cnt,h,z; ll sum; cin>>t; for(int k=1;k<=t;k++) { memset(a,0,sizeof(a)); memset(dp,0,sizeof(dp)); cin>>n>>m; for(int i=1;i<=n;i++) { cin>>a[i]; } sort(a+1,a+n+1); for(int i=1;i<=n;i++) { dp[i][1]=a[i]-a[1]; } for(int i=2;i<=m;i++) { for(int j=1;j<=n;j++) { dp[j][i]=INF; for(int k=1;j-k>=i-1;k++)//j-k代表上一个容器为止所装的所有数,必然大于容器数量i-1 { dp[j][i]=min(dp[j][i],dp[j-k][i-1]+a[j]-a[j-k+1]); } } } printf("Case #%d: %lld\n",k,dp[n][m]); } return 0; }
自己需要注意的问题: 在dp的时候常常用的数组下标是从1开始进行赋值的,所以在排序的时候是sort(a+1,a+n+1);