USACO16FEB:再探圆形谷仓(dp)

本文探讨了一个有趣的问题:如何在有限数量的入口下,使大量奶牛进入圆形谷仓并分布到指定房间的距离最短。通过将环形结构转换为链式结构,并采用动态规划的方法进行求解。

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

题目描述

After the last debacle involving Farmer John's circular barn, one would think he had learned his lesson about non-traditional architecture. However, he thinks he can still make his circular barn (from the preceding problem) function properly by allowing multiple cows into each room. To recap, the barn consists of a ring of nn rooms, numbered clockwise from 1 \ldots n1…n around the perimeter of the barn ( 3 \leq n \leq 1003≤n≤100 ). Each room has doors to its two neighboring rooms, and also a door opening to the exterior of the barn.

Farmer John wants exactly r_iri​ cows to end up in room ii ( 1 \leq r_i \leq 1,000,0001≤ri​≤1,000,000 ). To herd the cows into the barn in an orderly fashion, he plans to unlock kk exterior doors ( 1 \leq k \leq 71≤k≤7 ), allowing the cows to enter through only those doors. Each cow then walks clockwise through the rooms until she reaches a suitable destination. Farmer John wants to unlock the exterior doors that will cause his cows to collectively walk a minimum total amount of distance after entering the barn (they can initially line up however they like outside the kk unlocked doors; this does not contribute to the total distance in question). Please determine the minimum total distance his cows will need to walk, if he chooses the best kk such doors to unlock.

还是这个谷仓,有n(3<=n<=100)个房间。当然,奶牛可能不止n头了。奶牛都在谷仓外面。现在约翰想要让第i个房间关ri(1<=ri<=1000000)头奶牛按顺时针方向走,直到到达合适的房间。这k(1<=k<=7)个门开在哪里,才能使得奶牛们走的路程最少。奶牛在谷仓外可以随意移动,可以随意选择k个门中的任意一个排队,这不计入最终的路程。

输入输出格式

输入格式:

 

The first line of input contains nn and kk . Each of the remaining nn lines

contain r_1 \ldots r_nr1​…rn​ .

 

输出格式:

 

Please write out the minimum amount of distance the cows need to travel.

 

输入输出样例

输入样例#1: 复制

6 2
2
5
4
2
6
2

输出样例#1: 复制

14

说明

Farmer John can unlock doors 2 and 5. 11 cows enter at door 2 and walk a total

distance of 8 to get to rooms 2, 3, and 4. 10 cows enter at door 5 and walk a

total distance of 6 to get to rooms 5, 6 and 1.

思路:破环为链,dp[i][j][k]表示i房必须开门,i到j房共开k扇门,牛充满i到j房走过的距离。预处理O(k*n*n*n)暴力dp就行。

# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL num[203][203], a[203], dp[203][203][8];
int main()
{
    int n, K;
    scanf("%d%d",&n,&K);
    memset(dp, 0x3f, sizeof(dp));
    K = min(n, K);
    for(int i=1; i<=n; ++i) scanf("%lld",a+i), a[i+n] = a[i];
    for(int i=1; i<=2*n; ++i)
    {
        for(int j=i; j<=2*n&&j-i+1<=n; ++j)
        {
            num[i][j] = num[i][j-1] + a[(j<=n)?j:j-n]*(j-i);
            dp[i][j][1] = num[i][j];
        }
    }
    for(int k=2; k<=K; ++k)
        for(int i=1; i<=n&&i+k-1<=2*n; ++i)
            for(int j=i+k-1; j-i+1<=n; ++j)
                for(int t=i+k-1; t<=j; ++t)
                    dp[i][j][k] = min(dp[i][j][k], dp[i][t-1][k-1]+num[t][j]);
    LL ans = 0x3f3f3f3f3f3f3f3f;
    for(int i=1; i+n-1<=2*n; ++i)
        ans = min(ans, dp[i][i+n-1][K]);
    printf("%lld\n",ans);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值