題目傳送門
【題目大意】
把$m$塊餅乾分給$n$個孩子,第i個孩子有乙個貪婪度$g_i$,如果有$a_i$個孩子獲得的餅乾比第i個孩子多,那麼這個孩子就會產生$g_i*a_i$的怨氣值。求一種方案,保證每個孩子至少有一塊餅乾,並且使所有孩子的怨氣值總和最小。
【思路解析】
首先我們把孩子按照怨氣值從大到小排序,那麼他們所分到的餅乾一定是單調遞減的。設$f[i][j]$表示前$i$個孩子一共分到$j$塊餅乾時,這些孩子的怨氣值之和的最小值。再考慮轉移方程,有兩種情況:
1.第$i+1$個孩子獲得的餅乾數比第$i$個孩子少,此時$a[i+1]=i$
2.第$i+1$個孩子獲得的餅乾數與第$i$個孩子相同,此時還需要知道$i$前面有幾個孩子與$i$獲得的餅乾數也相同,才能計算出$a[i+1]$
因為在現有的dp狀態下,我們很難高效地維護這些資訊,所以我們不妨對狀態轉移做乙個等價轉換。
1.若第$i$個孩子獲得的餅乾數大於1,則等價與分配$j-i$個餅乾給前$i$個孩子,也就是每人少拿一塊餅乾,獲得的餅乾數的相對大小順序不變,從而怨氣值之和也不變。
2.若第$i$個孩子獲得的餅乾數為1,則列舉前面有多少個孩子也獲得一塊餅乾。
於是整個dp演算法的狀態轉移方程為:
$$f[i][j]=min\^g[p]\}(0\le k\le i)\}$$
初始值:$f[0][0]=0$
目標:$f[n][m]$
這道題啟發我們,有時可以通過額外的演算法確定dp狀態的計算順序,有時可以在狀態空間中運用等效手法進行縮放。
【**實現】
1 #include2**戳這裡#define rg register
3#define go(i,a,b) for(rg int i=a;i<=b;i++)
4using
namespace
std;
5const
int n=32,m=5002;6
const
int inf=1e9+7;7
intn,m;
8struct
qig[n];
11struct
ansa[n][m];
14int f[n][m],as
[n];
15bool cmp(qi a,qi b)
16int
main();
24 go(k,0,i-1)25
if(f[i][j]>f[k][j-(i-k)]+k*(g[i].num-g[k].num))
26 f[i][j]=f[k][j-(i-k)]+k*(g[i].num-g[k].num),a[i][j]=(ans);27}
28int t1=n,t2=m;
29while
(t1)
31else
32int tt=t1;t1=a[t1][t2].i;t2=a[tt][t2].j;33}
34 printf("
%d\n
",f[n][m]);
35 go(i,1,n) printf("
%d ",as
[i]);
36return0;
37 }
20181105題解報告
最後的模擬賽儘管打的很糟糕。某國個人所得稅法規定,普通公民的主要應納稅收入專案及納稅金額如下 工資 薪金所得。按月計算徵稅,以每月收入額減除費用800元後的餘額作為該月應納稅所得額,稅率如下表所示 級數月應納稅所得額 稅率 不超過500元的 超過500元 2000元的部分 超過2000元 5000元...
Mobile Service 題解報告
題目傳送門 題目大意 有l個位置 編號為1 l 和n個要求,初始狀態三個服務員分別在1,2,3號位置,每個要求給出乙個位置p i 需要乙個服務員到這個位置去,已知從位置i到位置j的費用為c i j 求最小費用。思路分析 我們用f i x y z 表示完成了前i個要求,三個服務員分別在x,y,z位置的...
cqm題解報告04
這題是道字串匹配問題。比較容易,賽間tle了多次。我真是傻。用兩次stack模擬就可以做了。下面附上 include include include include using namespace std const int maxn 2e5 10 char a maxn int main if a...