「火影完结纪念赛」木叶的军师
木叶的军师
(nara..pas./c./cpp)
时间限制:5s,空间限制:256MB
题目背景:
奈良鹿丸,拥有出众的应敌策略,头脑冷静、随机应变,IQ超过200。在第四次忍界大战时,父亲奈良鹿久死亡,鹿丸成为木叶乃至忍者联军的新任军师。最后成为了鸣人的左右手,与沙暴手鞠成婚……
题目描述:
既然是军师,鹿丸就必须要为木叶村的忍者编队。可是,他最怕麻烦了。所以它将这个任务交给了你。木叶村有T个中队,你需要将每个中队的n名忍者分为m个组。每个忍者都有一个能力值ai,每组人数不一定要相等,但每个忍者都要且只能被分在其中一个组中。每个组因为组员能力的差异,所以有一个“不默契值”,该值为本组的(maxa-mina)^2,请你帮鹿丸找出最优的分组方案,使a中队所有组的“不默契值”总和最小。
输入描述:
第一行一个整数T,表示有T个中队。
接下来T*2行,每两行表示一个中队。其中第一行为两个整数n,m,表示该中队的忍者数和要分的组数;第二行为n个数字依次表示这个中队每个忍者的能力值ai。
输出描述:
对于第i个中队,输出“Team i: x”,其中x为最小的“不默契值”总和。
样例输入:
2
5 2
1 3 4 8 2
3 1
1 2 3
样例输出:
Team 1: 9
Team 2: 4
数据范围:
20%的数据保证T<=4,n<=1000,m<=100。
100%的数据保证T<=7,n<=10000,m<=5000,保证所有运算不超过32位整数。数据保证是随机的。
题解
二维斜率优化裸题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#include<iostream> #include<set> #include<map> #include<cstdio> #include<cstring> #include<cstdlib> #include<ctime> #include<vector> #include<queue> #include<algorithm> #include<cmath> #define inf 2000000000 #define pa pair<int,int> #define ll long long using namespace std; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int T,tst,n,m,l,r,ans; int a[10005],g[10005],f[10005],q[10005]; int sqr(int x) { return x*x; } double cal(int j,int k) { return (double)(g[k]-g[j]+sqr(a[k+1])-sqr(a[j+1]))/(double)(a[k+1]-a[j+1]); } void add(int x) { while(l<r&&cal(q[r-1],q[r])>cal(q[r],x))r--; q[++r]=x; } void tran(int x) { l=1,r=0; for(int i=x;i<=n;i++) { add(i-1); while(l<r&&cal(q[l],q[l+1])<2*a[i])l++; int t=q[l]; f[i]=g[t]+sqr(a[i]-a[t+1]); } for(int i=1;i<=n;i++)swap(f[i],g[i]); } void dp() { ans=inf; for(int i=1;i<=n;i++) g[i]=sqr(a[i]-a[1]); for(int i=2;i<=m;i++) tran(i),ans=min(ans,g[n]); } int main() { T=read(); while(T--) { tst++; printf("Team %d: ",tst); n=read();m=read(); for(int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); n=unique(a+1,a+n+1)-a-1; dp(); printf("%d\n",ans); } return 0; } |
Subscribe