- #include
- using namespace std;
- using VI = vector<int>;
- using ll = long long;
- using PII = pair
int>; - const int mod = 998244353;
- int n;
- //第 i 个字母 状态为 j 的操作次数
- //dp[i][j] = dp[i-1][k]
-
- ll a[200050];
- ll dp[200050][8];//x y z
- ll x,y,z,xy,xz,yz,xyz;
-
- ll calc(ll h, int cur , int pre){
- //1 0
- //0 1
- //0 1
- int g[3] = {0,0,0};
- for(int i = 0 ; i <= 2 ; i++){
- if((cur>>i) & 1 && ((pre>>i) & 1) == 0){
- g[i] = 1;
- }
- }
- ll t;
- //3 4
- //
- if(g[0] == 0 && g[1] == 0 && g[2] == 0){
- t = 0;
- }else if(g[0] == 1 && g[1] == 0 && g[2] == 0){
- t = x - h % x;
- t %= x;
- }else if(g[0] == 1 && g[1] == 1 && g[2] == 0){
- t = xy - h % xy;
- t %= xy;
- }else if(g[0] == 1 && g[1] == 1 && g[2] == 1){
- t = xyz - h % xyz;
- t %= xyz;
- }else if(g[0] == 0 && g[1] == 1 && g[2] == 0){
- t = y - h % y;
- t %= y;
- }else if(g[0] == 0 && g[1] == 1 && g[2] == 1){
- t = yz - h % yz;
- t %= yz;
- }else if(g[0] == 0 && g[1] == 0 && g[2] == 1){
- t = z - h % z;
- t %= z;
- }else if(g[0] == 1 && g[1] == 0 && g[2] == 1){
- t = xz - h % xz;
- t %= xz;
- }
- return t;
-
-
-
- }
-
-
-
- int main(){
- cin>>n>>x>>y>>z;
- xy = x * y / __gcd(x,y);
- xz = x * z / __gcd(x,z);
- yz = z * y / __gcd(z,y);
- xyz = xy * z / __gcd(xy,z);
- for(int i = 1 ; i <= n ; i++) cin>>a[i];
-
- for(int i = 0 ; i <= n ; i++){
- for(int j = 0 ; j <= 7 ; j++){
- dp[i][j] = 1e18;
- }
- dp[i][0] = 0;
- }
- for(int i = 1 ; i <= n ; i++){
- for(int j = 0 ; j <= 7 ; j++){
- for(int k = 0 ; k <= 7 ; k++){
- dp[i][j] = min(dp[i][j] , dp[i-1][k] + calc(a[i] , j , k));
- }
- }
- }
- /* cout<
- cout<
- cout<
7]; -
-
- }
和网络赛没做出来的dp挺像的
类似就是状态枚举 , 考虑每个状态的花费 , 然后直接转移