- 题意
主人公把 n n n 道菜放进了烤炉里,每道菜有最佳的烹饪时间 t i t_i ti ,你要对每道菜选择一个 T i T_i Ti ,使得 ∑ i = 1 n ∣ T i − t i ∣ \sum_{i=1}^{n}|T_i-t_i| ∑i=1n∣Ti−ti∣ 最小,每道菜的 T i T_i Ti 不能相同。
- 思路
能贪心吗?不知道,似乎能,但又不好贪心,直接考虑动态规划。
首先排序,排完序之后就满足局部最优可以全局最优,或者说第 i i i 个菜可以从第 i − 1 i-1 i−1 道菜转移过来。
d p [ i ] [ j ] = m i n ( d p [ i ] [ j − 1 ] , d p [ i − 1 ] [ j − 1 ] + a b s ( a [ i ] − j ) ) dp[i][j] = min(dp[i][j-1],dp[i-1][j-1]+abs(a[i]-j)) dp[i][j]=min(dp[i][j−1],dp[i−1][j−1]+abs(a[i]−j))
d p [ i ] [ j ] dp[i][j] dp[i][j] 表示第 i i i 道菜,在第 j j j 分钟取出来的最小值。 - 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+10,mod=1e9+7;
template<typename T>
void Debug(T x,string s){
cout<<s<<": "<<x<<endl;
}
#define PII pair<int,int>
#define x first
#define y second
#define PB insert
int dp[N][499];
int a[N];
void solve()
{
int n;cin>>n;
for(int i = 1;i <= n;i ++) cin>>a[i];
sort(a+1,a+1+n);
memset(dp,0x3f3f3f3f,sizeof(dp));
for(int i = 0;i <= 2*n;i ++) dp[0][i] = 0;
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= n*2;j ++)
dp[i][j] = min(dp[i][j-1],dp[i-1][j-1]+abs(a[i]-j));
}
cout<<dp[n][2*n]<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
freopen("aout.txt","w",stdout);
#endif
int t;
scanf("%d", &t);
while (t--)
solve();
}