トピックリンク
タイトルの翻訳:
シェフのモノカープがn皿をオーブンに入れました。彼は最初のことを知っている私-course最適の調理時間は、T I分。
任意の正の整数時点Tで、Monocarpはオーブンから最大で1つの皿しか取り出せません。場合は、i番目の皿がで取り出されるT -番目の分、その不幸な値は| TtのI |。一度オーブンから取り出したら、元に戻すことはできません。
モノカープはすべての皿をオーブンから取り出し、彼が得ることができる最小の不幸な価値を求める必要があります。
問題解決のアイデア:
動的プログラミングの場合、配列f [i] [j]を使用して、i番目の分に最初のj皿から得られた最小の不幸な値を表します。
iとjには、それぞれ2つの状況があります.i分目に、j番目の皿が取られるか、j番目の皿が取られないかのどちらかです。
万一に備えて取る、つまり、最初のi-1分で最初のj-1皿を取り、次にi番目の分でj番目の皿を取ります。次に、不幸な値はf[i-1][j-1]+abs(t[j]-i)
です。ここで、t [j]はj番目の皿の最適な調理時間を表します。
万一に備えて服用しないでください、つまり、最初のj皿は最初のi-1分で撮影されます。不幸な値はf[i-1][j]
です。
したがって、状態遷移式はf[i][j]=min(f[i-1][j],f[i-1][j-1]+abs(t[j]-i))
です。
もう一つの問題は、iの範囲は何かということです。トンなので、私≤nは、すべての料理が最小不幸な値を得ることを前提に2 * n個以内に撮影することができます。
コード:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 410;
int T,n,t[N],f[N][N];
int main() {
// freopen("1.txt","r",stdin);
cin>>T;
while(T--) {
cin>>n;
for(int i=1; i<=n; i++) {
cin>>t[i];
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
f[i][j]=inf;
}
}
sort(t+1,t+n+1);
f[0][0]=0;
for(int i=1;i<=2*n;i++){
f[i][0]=0;
for(int j=n;j>=1;j--){
f[i][j]=min(f[i-1][j],f[i-1][j-1]+abs(t[j]-i));
}
}
cout<<f[2*n][n]<<endl;
}
return 0;
}
コードの最適化:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 410;
int T,n,t[N],f[N];
int main() {
// freopen("1.txt","r",stdin);
cin>>T;
while(T--) {
cin>>n;
for(int i=1; i<=n; i++) {
cin>>t[i];
}
for(int i=0;i<N;i++){
f[i]=inf;
}
sort(t+1,t+n+1);
f[0]=0;
for(int i=1;i<=2*n;i++){
for(int j=n;j>=1;j--){
f[j]=min(f[j],f[j-1]+abs(t[j]-i));
}
}
cout<<f[n]<<endl;
}
return 0;
}
総括する:
書くべきだった気がしますが、結局、こういう質問は前に書いた質問とほぼ同じです。
時間はたっぷりありますが。
まだ動的計画をブラッシュアップする必要があります