题目链接:https://codeforces.ml/contest/1437/problem/C
题意:T组样例
每组一个n,然后大小为n的数组a(1<=ai<=n)。然后要求取n个不一样的数bi且>0,然后计算sum(abs(ai-bi))的最小值。
题解:
很像是背包对不对,背包是怎样的,容量为n,然后dp[i]表示容量为i的时候的最大值。这题,可以转化为背包,不过dpi表示最小值。
//emmmm还是不擅长转化问题呀,简单题做多了emmm
代码:
#include <bits/stdc++.h>
#define ll long long
#define pi acos(-1)
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define pll pair<ll, ll>
#define fi first
#define se second
#define mp(x, y) make_pair(x, y)
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
template <class T> void read(T &x) {
T res = 0, f = 1;
char c = getchar();
while (!isdigit(c)) {
if (c == '-') f = -1;
c = getchar();
}
while (isdigit(c)) {
res = (res << 3) + (res << 1) + c - '0';
c = getchar();
}
x = res * f;
}
void print(ll x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
const ll maxn = 4e2 + 10;
const ll mod = 80112002;
ll n,a[maxn],vis[maxn];
ll dp[maxn];
// ll gcd(ll a,ll b){return (b==0)?a:gcd(b,a%b);}
// ll qpow(ll a,ll p,ll mod){ll
// ans=1;a=a%mod;while(p){if(p&1)ans=(ans*a)%mod;p>>=1;a=(a*a)%mod;}return ans;}
int main() {
ll _s = 1;
read(_s);
for (ll _ = 1; _ <= _s; _++) {
read(n);
mst(vis,0);
for(ll i=1;i<=n;i++) read(a[i]);
sort(a+1,a+1+n);
mst(dp,0x3f3f3f3f);
dp[0]=0;
for(ll i=1;i<=2*n;i++){
for(ll j=n;j>=1;j--){
dp[j]=min(dp[j],dp[j-1]+abs(a[j]-i));
}
}
cout<<dp[n]<<endl;
}
return 0;
}
/*
input:::
output:::
*/
再附上一段代码,之前看的别人的代码emmm。
dp[i][j]表示最大值i时取j个时的最小花费。转移是dp[i][j]->dp[i+1][j],dp[i][j]->dp[i+1][j+1]。。。dp,关注怎么转移的!!!(而且转移的上一步应该已经是最优子结构了)然后再直接上代码。
for(ll i=0;i<=2*n;i++) for(ll j=0;j<=n;j++) dp[i][j]=1e10;
dp[0][0]=0;
for(ll i=0;i<=2*n;i++){
for(ll j=0;j<=n;j++){
if(dp[i][j]<1e10){
dp[i+1][j]=min(dp[i+1][j],dp[i][j]);
dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]+abs(a[j+1]-(i+1)));
}
}
}
mi=1e10;
for(ll i=0;i<=2*n;i++) mi=min(mi,dp[i][n]);