思维+dp的一道题。
题意:有连续颜色1-N的史莱姆,可以花费a[i]的时间获得一个i颜色的史莱姆,也可以是魔法花费x的时间,让拥有的史莱姆颜色i变成i+1(n+1->1)。问最少需要多少时间,能获得所有颜色的史莱姆?
思路:这个题可以这样入手,需要第i个颜色的史莱姆,可以是直接获得第i个颜色的史莱姆,花费a[i]的时间,也可以获得i-m的颜色的史莱姆,花费a[i-m]+m*x的时间。
由于n+1->1,简单处理一下,使用a[i+n] = a[i],可以解决环的问题。
b[i][k]意思是使用k次咒语操作所用时间。
dp的递推式是:b[i][j] = min(b[i][j-1], a[j]);第i个史莱姆的获取要花费时间a[j]或者b[i][j-1]+x *k。
咒语可以年0-n-1次,所以sp表示咒语,循环从0-n-1:计数时cur = sp * x + b[i][i+sp];
然后循环所有颜色,取所有情况的最小值即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 4010;
int b[N][N];
int a[N];
int main()
{
int n, x;
scanf("%d %d", &n, &x);
for(int i = 0; i < n; i++)
{
scanf("%d", a + i);
a[i + n] = a[i];
}
for(int i = 0; i < n + n; i++)
{
b[i][i] = a[i];
for(int j = i + 1; j < n + n; j++)
{
b[i][j] = min(b[i][j-1], a[j]);
}
}
long long ans = (long long) 1e18;
for(int sp = 0; sp < n; sp++)
{
long long cur = sp * 1LL * x;
for(int i = 0; i < n;i++)
{
cur += b[i][i+sp];
}
ans = min(ans, cur);
}
cout << ans << endl;
return 0;
}
还有点东西,比如const N 代表数组大小,
比如全局变量单独拉出来,
比如 long long 的最大初始化 1e18,且进行乘法运算时不要忘记*1LL。