1 条题解

  • 0
    @ 2025-5-4 16:46:47

    本题要求根据不同客户租船天数及各选择的截止日期和金额,按客户请求顺序处理租船事宜,计算出最大利润。

    数据存储:用day[i]记录第i个客户想租船的天数;num[i][j]表示第i个客户在截止日期为j时能获得的最大金额;dp[j]表示在截止日期为j时能获得的最大利润。 状态转移: 遍历每个客户的选择,对于每个选择(a, b, c)(客户a,截止日期b,金额c),从截止日期b开始逆序遍历到day[a],更新num[a][j]为当前能获得的最大金额。逆序更新是因为要保证在同一截止日期下,不会重复计算同一个客户的租船收益。 遍历每个客户i,再从100逆序遍历到day[i],进行状态转移dp[j] = max(dp[j], dp[j - day[i]] + num[i][j]) 。这表示在截止日期j时,要么不选择该客户(保持dp[j]不变),要么选择该客户(在之前截止日期j - day[i]的最大利润基础上加上当前客户在截止日期j时能获得的最大金额)。 结果获取:最后遍历dp数组,找出其中的最大值,即为能获得的最大利润。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int dp[110];
    int num[110][110], day[110];
    int main()
    {
    	int t = 0, n, m, i, j, a, b, c, ans;
    	while (~scanf("%d", &n))
    	{
    		for (i = 1; i <= n; i++)
    			scanf("%d", &day[i]);
    		scanf("%d", &m);
    		memset(dp, 0, sizeof(dp));
    		memset(num, 0, sizeof(num));
    		while (m--)
    		{
    			scanf("%d%d%d", &a, &b, &c);     //客户  截止日期  获益
    			for (j = b; j >= day[a]; j--)    //在截止日期时收回,记得这里是逆序更新!
    			{
    				num[a][j] = max(num[a][j], c);
    				//printf("num[%d][%d] : %d\n", a, j, num[a][j]);
    			}
    		}
    		for (i = 1; i <= n; i++)
    			for (j = 100; j >= day[i]; j--)
    			{
    				dp[j] = max(dp[j], dp[j - day[i]] + num[i][j]);
    				//printf("dp[%d] : %d\n", j, dp[j]);
    			}
    		ans = 0;
    		for (i = 0; i <= 100; i++)
    			ans = max(ans, dp[i]);
    		if (t != 0)
    			printf("\n");
    		t++;
    		printf("%d\n", ans);
    	}
    }
    • 1

    信息

    ID
    279
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    8
    已通过
    1
    上传者