dp[i][j][k][used] = 현재 i번 째를 보고 있고 마지막으로 양자화되는 숫자가 j이고 남은 양자화 횟수가 k이고 이 j를 한 번이라도 양자화에 썼다면 used=1 일 때, 끝까지 양자화를 진행했을 때의 [i,n) 구간 에서의 최소값
정렬한 후에 구해주면 된다.
이 방법은 시간복잡도가 O(2TNS⋅MaxN) 이고 좀 최적화를 하면 500ms 정도로 통과된다.
constintinf=1e9;intdp[101][1001][11][2];voidsolve(){memset(dp,-1,sizeofdp);intn,s;cin>>n>>s;via(n);fv(a);sort(all(a));s=min(s,n);function<int(int,int,int,int)>fn=[&](inti,intj,intk,intused)->int{if(j>1000)returninf;if(i==n){if(k==s)returninf;return0;}int&ret=dp[i][j][k][used];if(~ret)returnret;ret=inf;// 현재 수로 양자화한다음 넘기기 if(used){ret=min(ret,(a[i]-j)*(a[i]-j)+fn(i+1,j,k,1));}else{if(k)ret=min(ret,(a[i]-j)*(a[i]-j)+fn(i+1,j,k-1,1));}// 양자화하는 수를 하나 증가시켜보기 if(k)ret=min(ret,fn(i,j+1,k,0));returnret;};cout<<fn(0,a[0],s,0)<<endl;}
Comments