[[problem:QUANTIZE]] 문제를 풀다가 왜 이런 결과가 되는지 궁금해서 질문드립니다....

  • pj4316
    pj4316

    QUANTIZE 문제를 풀다가 왜 이런 결과가 되는지 궁금해서 질문드립니다....

    제 알고리즘은
    1. 수열을 받아서 크기 순서대로 정렬
    2. group 배열과 elem_cnt 배열 을 하나 만들고, 양자화 할 수 있는 값들을 저장 시킵니다.
    3. 수열 값을 읽으면서 group에 값을 넣는데, 양자화 할 수 있는 수를 넘게 되면 최소 차이나는 값들을 하나의 값으로 합칩니다.
    그 합친 값들에 해당하는 elem_cnt를 하나 증가시킨다.
    4. 수열이 끝날때까지 연산을 계속한다.
    5. calculate()를 통해 오차값을 구합니다.

    Input :
    1
    9 3
    1 744 755 4 897 902 890 6 777

    Output :
    650

    (정답은 651)

    calculate() 함수 내에서 값을 하나하나 찍어보니 이곳에서 오류가 발생했는데 이유를 모르겠습니다.

    • ret=13, arr[3]=744, group[1]=759, pow(arr[i]+group[j],2)=225, ret + pow(arr[i]+group[j])=238

    • ret=237, arr[4]=755, group[1]=759, pow(arr[i]+group[j],2)=16, ret + pow(arr[i]+group[j])=253

    15^2 = 225 에 13을 더하면 238인데 ret가 237로 바꼈습니다...

    제가 만든 calculate() 함수에서 ret 덧셈연산중 1오차가 생기는 것이 발생하여서 질문합니다. 제 코드를 돌리다보면 side effect가 생겨서 1의 오차가 생기는 것인지 아니면 연산중에 제가 1을 빼는 것인지 궁금합니다. 고수님들 가르쳐주세요..ㅠ
    아래는 소스코드입니다.

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    #define INF 100000000000;
    
    int compare(const int &a, const int &b)
    {
        if(a <= b) return 1;
        else return 0;
    }
    
    void printArr(vector<double>& arr)
    {
        cout << "[";
        for(int i=0;i<arr.size();i++)
            cout << arr[i] << " ";
        cout << "]" << endl;
    }
    void printArr1(vector<int>& arr)
    {
        cout << "[";
        for(int i=0;i<arr.size();i++)
            cout << arr[i] << " ";
        cout << "]" << endl;
    }
    
    int getLowest(vector<double> &group)
    {
        double value = INF;
        int ret = -1;
        for(int i=0;i<group.size()-1;i++)
        {
            if(group[i] == group[i+1])
                return i;
            if(value > group[i+1]-group[i])
            {
                value = group[i+1]-group[i];
                ret = i;
            }
        }
        return ret;
    }
    
    void mergeGroup(vector<double> &group, vector<int> &elem_cnt, int index)
    {
        int elem = group[index+1];
        int cnt = elem_cnt[index+1];
    
    //    cout << "elem=" << elem << ",cnt="<< cnt << endl;
        group[index] = group[index]*elem_cnt[index] + elem*cnt;
        elem_cnt[index] += elem_cnt[index+1];
    
        group[index] /= elem_cnt[index];
        group.erase(group.begin()+index+1);
        elem_cnt.erase(elem_cnt.begin()+index+1);
    }
    
    int calculate(vector<int> &arr, vector<double>& group, vector<int>&elem_cnt)
    {
    
        printArr(group);
        printArr1(elem_cnt);
        int ret = 0;
        int j=0;
        for(int i=0;i<arr.size();i++)
        {
            if(elem_cnt[j] == 0)
                j++;
    
    
            if(group[j] - (int)group[j] > 0.5)
                group[j] = (int)group[j] + 1;
            else group[j] = (int)group[j];
    
            cout <<"ret=" << ret ;
            cout <<", arr["<<i<<"]=" << arr[i] ;
            cout <<", group["<<j<<"]=" << (int)group[j];
            cout <<", pow(arr[i]+group[j],2)=" << pow(arr[i] - (int)group[j], 2) ;
            cout <<", ret + pow(arr[i]+group[j])=" << ret + pow(arr[i] - (int)group[j], 2)<<endl;
            ret += pow(arr[i] - (int)group[j], 2);
    
            elem_cnt[j]--;
        }
        return ret;
    }
    
    int quantization(vector<int> &arr, int groupSize)
    {
        vector<double> group;
        vector<int> elem_cnt;
    
        stable_sort(arr.begin(),arr.end(),compare);
        //printArr1(arr);
    
        for(int i=0;i<arr.size();i++)
        {
            group.push_back((double)arr[i]);
            elem_cnt.push_back(1);
    
            if( group.size() > groupSize)
            {
                int index = getLowest(group);
    
                mergeGroup(group,elem_cnt,index);
            }
        }
    
        return calculate(arr,group,elem_cnt);
    }
    
    
    int main()
    {
    
    
        int num;
        int arrSize;
        int testcase;
        int groupSize;
        vector<int> arr;
    
        cin >> testcase;
    
        while(testcase--)
        {
            cin >> arrSize >> groupSize;
    
            for(int i=0;i<arrSize;i++)
            {
                cin >> num;
                arr.push_back(num);
            }
    
            cout << quantization(arr,groupSize) <<endl;
    
            arr.clear();
        }
        return 0;
    }
    

    7년 전
3개의 댓글이 있습니다.
  • Corea
    Corea

    우선 pow 함수는 실수형 연산입니다. 정수형 계산을 위해 이 함수를 사용하는 것은 지양하셔야 합니다.


    7년 전 link
  • pj4316
    pj4316

    감사합니다. 똑바로 안되던 계산은 처리했습니다.


    7년 전 link
  • Corea
    Corea

    넵 :) 혹시 더 질문 있으시면 올려주세요~


    7년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.