[CSP校内集训]hotel

题意

有n个房间分别有\(a_i\)个人\((a_i\leq 7)\),通过移动人的操作使得一个房间只能有\(0,4,7\)个人中的一种,花费1单位代价将一个人移动一格,无解输出-1

样例输入
7
1 0 7 0 0 0 3

样例输出
6

思路

DP直接搞,开始想的是用\(dp_{i,j}\)记录前\(i\)个房间都合法时多出来了\(j\)个人,但这样做\(j\)可能会越来越大

于是用\(dp_{i,j}\)表示从第\(i\)个房间向\(i+1\)移动了\(j\)个人后,使得第\(i\)个房间符合条件的最小代价

第i个房间进来的人可以通过上一层得到,枚举上一层和这一层转移即可,由于可能出现负数(即\(i+1\)\(i\)移动),下标需要加上一个数(这里加的是7)

Code

#include<bits/stdc++.h>
#define N 100005
#define Min(x,y) ((x)<(y)?(x):(y))
using namespace std;
typedef long long ll;
const ll inf = 10000000000000000;
int n,a[N];
ll f[N][15];

template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}

int main()
{
    freopen("hotel.in","r",stdin);
    freopen("hotel.out","w",stdout);
    read(n);
    for(int i=1;i<=n;++i) read(a[i]);
    for(int i=0;i<=n;++i)
      for(int j=0;j<=14;++j)
        f[i][j]=inf;
    
    f[0][7]=0;
    for(int i=1;i<=n;++i)
      for(int j=0;j<=14;++j)//now
        for(int k=0;k<=14;++k)//las
        {
            int in=k-7,out=j-7;
            int res=a[i]+in-out;
            if(res==0||res==4||res==7)  
              f[i][j]=Min(f[i][j],f[i-1][k]+abs(in));
        }
    cout<<(f[n][7]==inf ? -1 : f[n][7])<<endl;
    return 0;
}

讲道理这不是一道氵DP吗,考场上在想什么鬼

猜你喜欢

转载自www.cnblogs.com/Chtholly/p/11639483.html