Colorful Slimes( UPC 5594: 二维dp+思维)

5594: Colorful Slimes

时间限制: 2 Sec   内存限制: 256 MB
提交: 235   解决: 36
[ 提交][ 状态][ 讨论版][命题人: admin]

题目描述

Snuke lives in another world, where slimes are real creatures and kept by some people. Slimes come in N colors. Those colors are conveniently numbered 1 through N. Snuke currently has no slime. His objective is to have slimes of all the colors together.

Snuke can perform the following two actions:

Select a color i (1≤i≤N), such that he does not currently have a slime in color i, and catch a slime in color i. This action takes him ai seconds.

Cast a spell, which changes the color of all the slimes that he currently has. The color of a slime in color i (1≤i≤N−1) will become color i+1, and the color of a slime in color N will become color 1. This action takes him x seconds.

Find the minimum time that Snuke needs to have slimes in all N colors.

Constraints
2≤N≤2,000
ai are integers.
1≤ai≤109
x is an integer.
1≤x≤109

输入

The input is given from Standard Input in the following format:

N x
a1 a2 … aN

输出

Find the minimum time that Snuke needs to have slimes in all N colors.

样例输入

2 10

1 100

样例输出

12

提示

Snuke can act as follows:

Catch a slime in color 1. This takes 1 second.
Cast the spell. The color of the slime changes: 1 → 2. This takes 10 seconds.
Catch a slime in color 1. This takes 1 second.


题意:有两种选择:

操作【1】:直接制作颜色i,需要花费时间ai秒;

操作【2】:花费时间x秒,将所有存在的第i种颜色转变为第i+1种颜色(第n种颜色转化为第1种颜色);

问你 当n种颜色都存在花费的最小时间。

思路:

dp[i][k]表示整个过程使用了k次操作【2】,获得第i种颜色的最少花费时间(先不包括k*x)。


如果要想得到第i种颜色,它可以通过他之前的颜色进行转换也可直接制作,但实际上,不管通过什么方法,总是要先制作一种颜色才能转化为它(可以制作它本身实际就是转换0次),所以如果要让n种颜色集齐,实际怎么都得通过n次操作【1】。


再想,如果制作n种颜色的过程中,总共使用了k次第二种方法,那么在制作第i种颜色时,第i-1,i-2.....i-k种颜色其中一种必须存在,便可以在k次操作【2】中将它做出来。


因此在k次操作【2】的情况下若你想获得颜色i,你最少需要花费 min{ai, ai −1, … , ai − k} 秒(先不考虑花费k次操作【2】的时间,最后加上即可)就是制作i颜色前k次中的其中一种颜色花费最小的aj。所以如果执行k次操作【2】所花费的最小时间就为 k*x+(b[1][k]+b[2][k]+.....b[n][k])。


动态转移方程为 b[i][k]=min(b[i][k-1],a[i-k])


代码实现:


#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=2e3+10;
ll dp[maxn][maxn];
int main()
{
	ll n,x;
	cin>>n>>x;
	ll ans=1e18;
	for(int i=1;i<=n;i++)
		cin>>dp[i][0];
		int t;
	for(int i=1;i<=n;i++)
		{
			for(int k=1;k<=n-1;k++)
			{
				t=i-k;
				if(t<=0)
				t=n+t;
				dp[i][k]=min(dp[i][k-1],dp[t][0]);
			}
		}
		ll sum=0;
		for(int k=0;k<=n-1;k++)
		{
			sum=0;
			for(int i=1;i<=n;i++)
			{
				sum+=dp[i][k];
			}
			ans=min(ans,sum+k*x);
		}
		cout<<ans<<endl;
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值