题目链接:D. Armchairs
思路:我们将0的位置放在一个数组中,将1位置放在一个数组中,我们规定每一个1位置都是有序的,即顺序不可以被改变,\(f(i,j)\)表示处理完前i个人,且第i个人坐在第j个板凳上的最小花费,显然\(f(i,j) = min_{p=i-1}^{p=j-1}f(i-1,p) + dis(a[i],a[j])\)然后可以写出\(\Theta(n^3)\)的动态规划,发现\(min_{p=i-1}^{p=j-1}f(i-1,p)\)可以通过处理前缀取\(min\)。\(\Theta(1)\)求解,所以降为\(\Theta(n^2)\)
\(Code:\)
/* -*- encoding: utf-8 -*- ''' @File : 255.cpp @Time : 2021/05/31 21:05:02 @Author : puddle_jumper @Version : 1.0 @Contact : 1194446133@qq.com ''' # here put the import lib*/ #include<set> #include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<cstdlib> #include<map> #include<algorithm> #include<vector> #include<queue> #define ch() getchar() #define pc(x) putchar(x) #include<stack> #include<unordered_map> #define rep(i,a,b) for(auto i=a;i<=b;++i) #define bep(i,a,b) for(auto i=a;i>=b;--i) #define lowbit(x) x&(-x) #define ll long long #define ull unsigned long long #define pb emplace_back #define mp make_pair #define PI acos(-1) using namespace std; template<typename T>void read(T&x){ static char c; static int f; for(c=ch(),f=1; c<'0'||c>'9'; c=ch())if(c=='-')f=-f; for(x=0; c>='0'&&c<='9'; c=ch())x=x*10+(c&15); x*=f; } template<typename T>void write(T x){ static char q[65]; int cnt=0; if(x<0)pc('-'),x=-x; q[++cnt]=x%10,x/=10; while(x) q[++cnt]=x%10,x/=10; while(cnt)pc(q[cnt--]+'0'); } const int N = 5e3+10; int n,a[N]; int f[N][N]; int b[N],c[N],totb ,totc; int d[N][N]; void solve(){ read(n); memset(f,0x3f,sizeof f); rep(i,1,n)read(a[i]); rep(i,1,n){ if(a[i] == 1)b[++totb] = i; else c[++totc] = i; } f[0][0] = 0; rep(i,1,totb){ rep(j,i,totc-totb+i){ f[i][j] = d[i-1][j-1] + abs(b[i]-c[j]); if(j == i)d[i][j] = f[i][j]; else d[i][j] = min(f[i][j],d[i][j-1]); // rep(p,0,j-1)f[i][j] = min(f[i][j],f[i-1][p]+abs(b[i]-c[j])); } } int ans = 9999999; if(totb == 0)ans = 0; rep(i,totb,totc)ans = min(ans,f[totb][i]); write(ans); } signed main(){solve();return 0; }