【AtCoder】【DP】Colorful Slimes(AG004)

題意:

有N種顏色的史萊姆,每種顏色有無線多個史萊姆。每次可以花Ai的代價抓一隻沒有的史萊姆,或者是花費x的代價讓已經有的所有的史萊姆的顏色+1(顏色爲N的變爲1)。

數據範圍:

1<=N<=10^5 1<=x<=10^9

思路:

因爲可以讓其他的史萊姆通過變換顏色來得到當前我們想要的史萊姆,所以說一種顏色的史萊姆顯然是要被多次捕捉的。然後,我們可以發現,第二種操作的全局的移動次數實際上是移動次數最大的那隻史萊姆的移動次數。因爲不可能一隻史萊姆的初始顏色相同並且滿足顏色+1的次數也相同,那麼上述性質是成立的。
我最開始想到的是一個n^3的DP,也就是枚舉一個最大的顏色+1的次數,然後在這個次數限制下,枚舉一種顏色,再在限制範圍內枚舉,找到得到這種顏色花費最少的方法,但是太低效了。
可以考慮從小到大枚舉顏色+1的次數,然後當前對於某種顏色就可以利用之前已經算出來的信息(因爲顏色+1次數 < 當前顏色+1次數的途徑是合法的),只對於當前這一次新多出來的轉移方式取min,就可以求得得到當前這種顏色的最小代價了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 2000
#define INF 1000000000000000000LL
using namespace std;
typedef long long LL;
int N;
LL b[MAXN+5],a[MAXN+5],x;
int main()
{
//	freopen("slime.in","r",stdin);
//	freopen("slime.out","w",stdout);
	scanf("%d %lld",&N,&x);
	for(int i=0;i<N;i++)
		scanf("%lld",&a[i]);
	fill(b,b+N,INF);
	LL ans=INF;
	for(int mv=0;mv<N;mv++)
	{
		LL ansn=0;
		for(int i=0;i<N;i++)
			b[i]=min(b[i],a[(i-mv+N)%N]);//只考慮當前的最遠的轉移,利用之前的信息
		for(int i=0;i<N;i++)
			ansn+=b[i];
		ansn+=mv*x;
		ans=min(ans,ansn);
	}
	printf("%lld\n",ans);
	return 0;
}

代碼還是比較簡單的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章