首页 > 编程语言 >算法_dp

算法_dp

时间:2023-01-27 15:12:18浏览次数:56  
标签:int up 某队 down 算法 101 dp

2023牛客寒假算法基础集训营1 B题 四维dp+前缀和处理

题目描述

众所周知,2022年是四年一度的世界杯年,那么当然要整点足球题。本题需要你模拟一支队伍的一赛季联赛征程。

联赛的规则是,踢若干场比赛。每赢一场(进球数大于对方)比赛得3分,每输一场比赛(进球数小于对方)得0分,每次平局(进球数等于对方)得1分。
已知在接下来一个赛季的n轮比赛里,某队一共进了x个球,而某队的n个对手在和某队的比赛中一共进了y个球。求这n轮有多少种不同的比赛结果使得本赛季某队获得至m分。
之中对于两种比赛结果,若n轮比赛中至少有一场的比分不一样,就认为两种比赛结果不同。

输入描述:

输入仅包含一行四个整数
n,m,x,y(1≤n≤40,0≤m≤120,0≤x,y≤100),之间用空格分隔开,含义如题目所述。

输出描述:

输出一个数字,为答案对998244353取模的结果。


#include <iostream>
using namespace std;

int n, m, x, y;
const int mod = 998244353;
const int N = 41 * 3;

int dp[125][101][101];
int line[125][101][101], down[125][101][101], up[125][101][101];

/*
思路:
    dp[i][j][s][t]表示前i场比赛中总得分为j,a队得分s,b队得分t的种类数。
    若输了  +=dp[i-1][j][s-k][t-l] (k=0-s,l=0-t,k<l)    //左侧45°梯形
    若赢了  +=dp[i-1][j-3][s-k][t-l] (k=0-s,l=0-t,k>l) //youce
    平      +=dp[i-1][j-3][s-k][t-l] (k=0-s,l=0-t,k=l) //对角线

代码;
    现预处理出down,up,line的数组值,在依次枚举,因队dp[i][j][s][t]仅用到dp[i-1]可省去一维,对上一维的数据处理其

    1、若球队一直赢时,得分最高位n*3,而不是题目中的m,m是最小计算种类数的值
    2、down,line,up三个数组初始化时,down表示的是左侧角等于45的左侧梯形的所有dp[i-1][j][s][t]的和,up也是如此
    3、dp数组迭代时,若球队本场赢了,dp[j][s][t]+=down[j][s][t-1],而不是用up数组,down数组表示球队赢得多。
*/

int main()
{
    cin >> n >> m >> x >> y;
    dp[0][0][0] = 1;

    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= n * 3; j++)
        {
            for (int s = 0; s <= x; s++)
                down[j][s][0] = line[j][s][0] = dp[j][s][0];
            for (int t = 0; t <= y; t++)
                up[j][0][t] = line[j][0][t] = dp[j][0][t];

            for (int u = 1; u <= x; u++)
            {
                for (int v = 1; v <= y; v++)
                {
                    line[j][u][v] = (line[j][u - 1][v - 1] + dp[j][u][v]) % mod;
                }
            }
            for (int u = 0; u <= x; u++)
            {
                for (int v = 0; v <= y; v++)
                {
                    if (v)
                        down[j][u][v] = (down[j][u][v - 1] + line[j][u][v]) % mod;
                    if (u)
                        up[j][u][v] = (up[j][u - 1][v] + line[j][u][v]) % mod;
                }
            }
        }

        for (int j = 0; j <= n * 3; j++)
        {
            for (int s = 0; s <= x; s++)
            {
                for (int t = 0; t <= y; t++)
                {
                    dp[j][s][t] = 0;
                    if (j >= 0)
                    {
                        if (t)
                            dp[j][s][t] += down[j][s][t - 1];
                        dp[j][s][t] %= mod;
                    }
                   
                    if (j >= 3)
                    {
                        if (s)
                            dp[j][s][t] += up[j - 3][s - 1][t];
                        dp[j][s][t] %= mod;
                    }
                       
                    if (j >= 1)
                        dp[j][s][t] += line[j - 1][s][t];
                    dp[j][s][t] %= mod;
                }
            }
        }
    }
    int ans = 0;
    for (int i = m; i <= n*3; i++)
    {
        ans += dp[i][x][y];
        ans %= mod;
    }
    cout << ans << endl;
    return 0;
}

标签:int,up,某队,down,算法,101,dp
From: https://www.cnblogs.com/ccag/p/17068914.html

相关文章