网创优客建站品牌官网
为成都网站建设公司企业提供高品质网站建设
热线:028-86922220
成都专业网站建设公司

定制建站费用3500元

符合中小企业对网站设计、功能常规化式的企业展示型网站建设

成都品牌网站建设

品牌网站建设费用6000元

本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...

成都商城网站建设

商城网站建设费用8000元

商城网站建设因基本功能的需求不同费用上面也有很大的差别...

成都微信网站建设

手机微信网站建站3000元

手机微信网站开发、微信官网、微信商城网站...

建站知识

当前位置:首页 > 建站知识

【基础DP,但注意写法上的细节】-创新互联

AcWing 80 场周赛 4727.摆放棋子 算法:动态规划
  1. f ( i , j , k , u ) f(i, j, k, u) f(i,j,k,u) —— 表示选 i i i 个黑子, j j j 个白子,末尾有连续 k k k 个棋子, u = 0 u = 0 u=0 表示末位是黑子, u = 1 u = 1 u=1 表示末位是白子。

    创新互联主营新乡网站建设的网络公司,主营网站建设方案,重庆APP软件开发,新乡h5小程序开发搭建,新乡网站营销推广欢迎新乡等地区企业咨询
  2. 状态转移方程:若末位只有一个连续棋子需要特判

f ( i , j , k , 0 ) = f ( i − 1 , j , k − 1 , 0 ) f(i, j, k, 0) = f(i - 1, j, k - 1, 0) f(i,j,k,0)=f(i−1,j,k−1,0)

f ( i , j , k , 1 ) = f ( i , j − 1 , k − 1 , 1 ) f(i, j, k, 1) = f(i, j - 1, k - 1, 1) f(i,j,k,1)=f(i,j−1,k−1,1)

f ( i , j , 1 , 0 ) + = f ( i − 1 , j , k , 1 ) f(i, j, 1, 0) += f(i - 1, j, k, 1) f(i,j,1,0)+=f(i−1,j,k,1)

f ( i , j , 1 , 1 ) + = f ( i , j − 1 , k , 0 ) f(i, j, 1, 1) += f(i, j - 1, k, 0) f(i,j,1,1)+=f(i,j−1,k,0)

时间复杂度 O ( n 1 n 2 × ( k 1 + k 2 ) ) O(n_1 n_2 \times (k_1 + k_2)) O(n1​n2​×(k1​+k2​))
#include#include 
#include#define endl '\n'

#define fup(i, a, b) for (int i = a; i<= b; i ++ )
#define fdn(i, a, b) for (int i = a; i >= b; i -- )

using namespace std;

typedef long long LL;

const int N = 110, M = 15, MOD = 1e8;

int n, m, x, y;
int f[N][N][M][2];

void add(int &a, int b)
{a = (a + b) % MOD;
}

int main()
{cin >>n >>m >>x >>y;
    
    f[1][0][1][0] = f[0][1][1][1] = 1;
    fup(i, 0, n) fup(j, 0, m)
    {if (i) 
        {fup(k, 2, x) f[i][j][k][0] = f[i - 1][j][k - 1][0];
            fup(k, 1, y) add(f[i][j][1][0], f[i - 1][j][k][1]);
        }
        if (j)
        {fup(k, 2, y) f[i][j][k][1] = f[i][j - 1][k - 1][1];
            fup(k, 1, x) add(f[i][j][1][1], f[i][j - 1][k][0]);
        }
    }
    
    int res = 0;
    fup(i, 1, x) add(res, f[n][m][i][0]);
    fup(i, 1, y) add(res, f[n][m][i][1]);
    
    cout<< res<< endl;
    
    return 0;
}

简洁写法
  1. f ( i , j , k ) f(i, j, k) f(i,j,k) 表示摆好前 i i i 个棋子,其中有 j j j 个白棋, k = 0 k = 0 k=0 表示最后一位为黑棋, k = 1 k = 1 k=1 表示最后一位为白棋。

  2. 状态转移方程:若最后一位是白棋,则枚举砍掉最后多少位后剩下的序列的最后一位是黑棋,这里枚举砍掉 k k k 位的范围是 1 ⩽ k ⩽ m i n ( j , x ) 1 \leqslant k \leqslant min(j, x) 1⩽k⩽min(j,x),表示最后砍掉的部分不能超过当前枚举的连续段的上限以及题目所给的连续长度的上限,下面同理;若最后一位是黑棋,则枚举砍掉最后多少位后剩下的序列的最后一位是白棋,这里枚举砍掉 k k k 位的范围是 1 ⩽ k ⩽ m i n ( i − j , y ) 1 \leqslant k \leqslant min(i - j, y) 1⩽k⩽min(i−j,y)。

f ( i , j , 1 ) + = f ( i − k , j − k , 0 ) f(i, j, 1) += f(i - k, j - k, 0) f(i,j,1)+=f(i−k,j−k,0)

f ( i , j , 0 ) + = f ( i − k , j , 1 ) f(i, j, 0) += f(i - k, j, 1) f(i,j,0)+=f(i−k,j,1)

时间复杂度 O ( ( n 1 + n 2 ) × k 2 ) O((n_1 + n_2) \times k_2) O((n1​+n2​)×k2​)
#include#include 
#include#define endl '\n'

#define fup(i, a, b) for (int i = a; i<= b; i ++ )
#define fdn(i, a, b) for (int i = a; i >= b; i -- )

using namespace std;

const int N = 110, M = N<< 1, S = 15, MOD = 1e8;

int n, m, x, y;
int f[M][N][S];

int add(int &a, int b) 
{return a = (a + b) % MOD;
}

int main()
{cin >>n >>m >>x >>y;
    n += m;
    
    f[0][0][0] = f[0][0][1] = 1;
    fup(i, 1, n) fup(j, 0, min(i, m))
    {fup(k, 1, min(j, y)) add(f[i][j][1], f[i - k][j - k][0]);
        fup(k, 1, min(i - j, x)) add(f[i][j][0], f[i - k][j][1]);
    }
    
    cout<< add(f[n][m][0], f[n][m][1])<< endl;
    
    return 0;
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页标题:【基础DP,但注意写法上的细节】-创新互联
地址分享:http://bjjierui.cn/article/cddeih.html

其他资讯