洛谷P2503 [HAOI2006]均分資料(隨機化貪心)
現在來看這個題就是水題,但模擬賽時想了1個小時貪心,推了一堆結論,最後發現貪心做
不了,
又想了半個小時dp 發現dp好像也做不了,在隨機化貪心和模擬退火
選了模擬退火但寫炸了。(我怎麼這麼水)。我們來看這個題,採取
隨機化貪心,利用random_shuffle函式將所有數字不停隨機
化,每次
隨機化後貪心的取就可以,因為採取的是隨機化貪心,所以貪心策略不必最優,我們用x陣列去存
儲每個位置的值,列舉每一個數字,將數字加到最小的位置即可,我們已知最小位置的值一定小
於品均數,所以加到最小位置是較優的。
放程式碼吧
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<ctime>
#include<algorithm>
using namespace std;
const int maxn=1e4;
int n,m;
int a[maxn];
int x[maxn];
double xl,ans=0x3f3f3f3f;
void slove(){
memset(x,0,sizeof(x));
for(int i=1;i<=n;i++){
int p=1;
for(int j=1;j<=m;j++){
if(x[j]<x[p])
p=j;
}
x[p]+=a[i];
}
double cnt=0;
for(int i=1;i<=m;i++){
cnt+=pow(xl-x[i],2);
}
cnt=cnt/(double)m;
ans=min(ans,cnt);
}
int main(){
// freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
double add=0;
for(int i=1;i<=n;i++){
cin>>a[i];
add+=a[i];
}
xl=add/m;
// cout<<xl<<endl;
int t=100000;
while(t--){
random_shuffle(a+1,a+1+n);
slove();
}
ans=sqrt(ans);
printf("%.2f",ans);
return 0;
}
```P2503 [HAOI2006]均分資料 隨機化貪心