1. 程式人生 > 實用技巧 >hdu4283 You Are the One

hdu4283 You Are the One

題目連結:https://vjudge.net/problem/HDU-4283

題意:n個人,每個人有一個值di,如果他是第k個上場的,那麼他會產生(k-1)*di的不開心值。給定一個棧重新排列這n個人,求最小的不開心值

這題的方程有點玄學......顯然貪心是不行的,因為這個棧不能任意調換順序。設f[i][j]表示將i到j的人放到棧裡再出棧的最小值(這兒就把i想成棧中的第一個人,先不考慮i前面的人)。顯然i會先進棧,並且i可以在i到j的任意一個位置出棧,於是可以列舉i出棧的位置,從i到j一共有j-i+1種可能,假設i是第k個出棧的,則有如下的轉移方程:

f[i][j]=min(f[i][j],f[i+1][i+k-1]+(k-1)*di+f[i+k][j]+k*(s[j]-s[i+k-1])),這兒的最後一項就是把前i+k個人對i+k到j產生的影響加起來

#include<bits/stdc++.h>
using namespace std;

const int N=110;
int d[N],f[N][N],s[N],t,n,i,j,k,l,T;
/* f[i][j]表示i~j出棧的最小值(不考慮i~j之前的數)*/ 

int main(){
	scanf("%d",&t); T=t;
	while (t--){
	  memset(f,0,sizeof(f));
	  scanf("%d",&n);
	  for (i=1;i<=n;i++) {
	  	scanf("%d",&d[i]); s[i]=s[i-1]+d[i]; 
	  }
	  for (l=1;l<n;l++)
	    for (i=1;i<n;i++){
	      j=i+l;
	      if (j>n) continue;
	      f[i][j]=1e7;
	      for (k=1;k<=j-i+1;k++) //列舉Di的位置,從i~j共j-i+1種 
	        f[i][j]=min(f[i][j],f[i+1][i+k-1]+(k-1)*d[i]+f[i+k][j]+k*(s[j]-s[i+k-1])); //*
		}
	  printf("Case #%d: %d\n",T-t,f[1][n]);
	}
	return 0;
}

到這兒kuangbin22也大致刷完了,除了zoj3537要用點凸包的東西(咕咕咕)。說實話自己只獨立做出來簡單的,大部分是想了挺久,然後要瞅一眼提示做出來;像hdu2476這種先刷空串再遞推的是看了題解之後寫的了,不知道是怎麼想出來的。有空把kuangbin 5 12 22寫個小總結,7也在進行中......