CF GYM 100703F Game of words

本文探讨了两人轮流选择并完成多个游戏的最优策略,通过动态规划算法找到最短完成时间。详细介绍了状态转移方程及代码实现,提供了解题思路与技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:两个人玩n个游戏,给出每人玩每个游戏的时间,两个人需要在n个游戏中挑m个轮流玩,求最短时间。

 

解法:dp。(这场dp真多啊……话说也可以用最小费用最大流做……然而并不会XD)dp[i][j][k]表示玩前i个游戏时第一个人玩了j个游戏,第二个人玩了k个游戏,所以状态转移方程为dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - 1][k] + a[i], dp[i - 1][j][k - 1] + b[i]),第一个维度在空间上可以优化掉,再处理一下边界,但是如果写成dp[i][j + 1][k] = dp[i - 1][j][k] + a[i], dp[i][j][k + 1] = dp[i - 1][j][k] + b[i]看起来更优美……不需要处理边界……但是跟我的思考方式有些不同……

 

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
int a[405], b[405];
int dp[405][405];
int main()
{
    int n, m;
    while(~scanf("%d%d", &m, &n))
    {
        for(int i = 0; i < n; i++)
            scanf("%d", &a[i]);
        for(int i = 0; i < n; i++)
            scanf("%d", &b[i]);
        memset(dp, 0x3f3f3f3f, sizeof dp);
        dp[0][0] = 0;
        for(int i = 0; i < n; i++)
        {
            for(int j = i + 1; j >= 0; j--)
            {
                for(int k = i - j + 1; k >= 0; k--)
                {
                    if(j == 0 && k == 0)
                        continue;
                    if(j == 0)
                        dp[j][k] = min(dp[j][k], dp[j][k - 1] + b[i]);
                    else if(k == 0)
                        dp[j][k] = min(dp[j][k], dp[j - 1][k] + a[i]);
                    else
                        dp[j][k] = min(dp[j][k], min(dp[j - 1][k] + a[i], dp[j][k - 1] + b[i]));
                }
            }
        }
        printf("%d\n", min(dp[m / 2][m - m / 2], dp[(m + 1) / 2][m - (m + 1) / 2]));
    }
    return 0;
}

  

转载于:https://www.cnblogs.com/Apro/p/4685790.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值