Programming thinking week4 homework

WEEK 4 Assignment

To sum up

A: Fear of DDL

n assignments, each assignment has its own DDL, if you can't complete the assignment before DDL, you need to deduct the corresponding score. Find the minimum deduction points for input assignments.

1.Sample Input and Outout

Input

The input contains T test cases. The first line of input is a single integer T, the number of test cases.

Each test case starts with a positive integer N (1 <= N <= 1000), indicating the number of jobs.

Then two lines. The first line contains N integers, indicating DDL, and the next line contains N integers, indicating points deducted.

3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4

Outout

For each test case, you should output the smallest total reduction score, one line per test case.

0
3
5

2. Topic idea and code

A question to practice the greedy algorithm. The greedy criterion is to traverse from the last deadline and give priority to the homework with the most points deducted. After entering the DDL and deduction points of the job, sort the job. The first key value is the DDL date and the second key value is the deduction point. The sorting criteria are from small to large. Then traverse from the last DDL as the current date, select the job that has not yet expired and deduct the most points from the current date, and delete the item in the job array. If you encounter p.back (). DDL <date, it means that there is no work you can do on the current date, then continue to traverse forward until the first day is traversed. The deducted sum of the remaining jobs in the final array is the optimal solution.
code show as below:

#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int num;
int LostPoint;
class hwk
{
public:
    hwk()
    {
        DDL=0;
        de=0;
    }
    hwk(int a,int b)
    {
        DDL=a;
        de=b;
    }
public:
    int DDL;
    int de;//减分
};

vector<hwk> p;

bool cmp(hwk a,hwk b)
{
    if(a.DDL<b.DDL)
        return true;
    else if(a.DDL==b.DDL&&a.de<b.de)
        return true;
    else return false;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        LostPoint=0;
        p.clear();
        cin>>num;
        for(int j=0;j<num;j++)
        {
            int ddl;
            cin>>ddl;
            p.push_back({ddl,0});
        }//输入作业DDL
        for(int j=0;j<num;j++)
        {
            int De;
            cin>>De;
            p[j].de=De;
        }//输入每个作业相应扣除的分数
        sort(p.begin(),p.begin()+num,cmp);
        //按照作业优先度排序
        for(int date=p.back().DDL;date>=1;date--)
        {
            //cout<<"date:"<<date<<endl;
            if(p.empty())
                break;
            if(p.back().DDL<date)
                continue;
            int max=p.size()-1;
            int k=p.size()-1;
            //挑选所有还未过期且具有最大减分值的作业
            while(p[k].DDL>=date&&k>=0) {
                //cout<<max<<' ';
                if (p[max].de < p[k].de)
                    max = k;
                k--;
            }
            //将这个作业做掉
            p.erase(p.begin()+max,p.begin()+max+1);
        }
        //计算最优失分值。
        while(!p.empty())
        {
            LostPoint=LostPoint+p.back().de;
            p.pop_back();
        }
        cout<<LostPoint<<endl;
    }
    return 0;
}

B: Four series

Four series A, B, C, D, each series has n numbers.
If you take a number from each sequence, find out how many schemes make the sum of the four numbers zero.

1. Sample Input and Out

Input

The first row: n (representing the number of numbers in the sequence) (1≤n≤4000)

In the next n rows, the i-th row has four numbers, which represent the i-th number in the sequence A, B, C, D
(the number does not exceed the 28th power of 2)

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Output

The number of different combinations is output.

5

Note:

样例解释: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

2. Topic idea and code

It's a problem of practicing dichotomy. Since n <= 4000, a dichotomy is needed to reduce complexity. The method is to first calculate the sum of sequence A and sequence B to store and sort. Then, in the new sequence, find the opposite of the sum of the elements of sequence C and sequence D. The complexity can be reduced to O (n ^ 2 + 2logn). In this, pay attention to the use of the equal sign when determining the boundary by binary search.

code show as below:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n;
int result=0;
int* A;
int* B;
int* C;
int* D;
vector<int> p1;

void count(int a)
{

    int tar1=0;//标记>=a的首个位置
    int tar2=0;//标记<=a的最后一个位置
    int st=0;//起始指针
    int end=p1.size()-1;//末尾指针
    int mid=(st+end)/2;//中间指针
    //cout<<'!'<<endl;
    while(st<=end)
    {
        //cout<<'!'<<endl;
        if(a<=p1[mid]) {
            tar1=mid;
            end = mid - 1;
            mid=(st+end)/2;
        }
        else {
            st = mid + 1;
            mid = (st + end) / 2;
        }
    }
    if(p1[tar1]!=a)
        return ;

    st=0;
    end=p1.size()-1;
    while(st<=end)
    {
        if(a>=p1[mid]) {
            tar2=mid;
            st = mid + 1;
            mid=(st+end)/2;
        }
        else {
            end = mid - 1;
            mid=(st+end)/2;
        }
    }
    result=result+(tar2-tar1+1);
}

int main()
{
    cin>>n;
    A=new int[n];
    B=new int[n];
    C=new int[n];
    D=new int[n];
    for(int i=0;i<n;i++)
    {
        cin>>A[i];
        cin>>B[i];
        cin>>C[i];
        cin>>D[i];
    }
    for(int i=0;i<n;i++) {
        for (int j = 0; j < n; j++)
            p1.push_back(A[i] + B[j]);
    }
    sort(p1.begin(),p1.begin()+p1.size());

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            count(-(C[i]+D[j]));
    }
    cout<<result<<endl;
    return 0;
}

The mysterious gift of C TT

Given an array of N numbers cat [i], and use this array to generate a new array ans [i]. The new array is defined as for any i, j and i! = J, all have ans [] = abs (cat [i]-cat [j]), 1 <= i <j <= N. Try to find the median of this new array. The median is the number corresponding to the (len + 1) / 2 position after sorting, and '/' is rounded down.

1. Sample Input and Out

Input

Multiple sets of input, each time enter an N, which means that there are N numbers, and then enter a sequence cat of length N, cat [i] <= 1e9, 3 <= n <= 1e5

4
1 3 2 4
3
1 10 2

Output

Output the median of the new array ans

1
8

2. Topic idea and code

The answer dichotomy was used to find the median, and the dichotomy was also used when searching the new array newList, which shared two dichotomy.
First sort the input sequence to ensure that it is always positive (j> i) in xj-xi to remove the absolute value. If the size of the input sequence is n, the size of the new sequence is N = n * (n-1) / 2. If N is an odd number, N ++, ensure that N / 2 must be the median of the new sequence.
Then make a dichotomous answer. The left boundary is 0, and the right boundary is the maximum value minus the minimum value of the original sequence. Let the middle number P = (l + r) / 2. Calculate the number of binary groups that satisfy the condition (xj-xi) <= P. If it is less than N / 2, the left boundary moves right to P + 1, otherwise, the left boundary moves to P.
Now we only need to solve the problem of counting the eligible binary. Rewrite the condition (xj-xi) <= P as xi> = xj + P. Traverse j in the main function and search for i that meets the condition for each j. In the find function, xj + P is a fixed value, find the first element subscript ans that meets the condition> = xj + P in the original number sequence, j-ans is the number of i in the sequence that determines that j meets the condition number. Sum all j to get the number of qualified duals.
code show as below:

#include<iostream>
#include<algorithm>
#include <cstdio>
using namespace std;
int n,N;
int P,tmp;
int* List;
int  l, r, ans,mid;


//返回newList中满足<=P的二元组(i,j)个数
int find(int p,int j)
{
    int L = 0, R = j;
    ans=j;
    while(L<R)
    {
        mid=(L+R)/2;
        if(List[mid]>=List[j]-P)
        {
            ans=mid;
            R=mid;
        } else{
            L=mid+1;
        }
    }
    return j-ans;
}

int main()
{
    while(cin>>n)
    {
        N=n*(n-1)/2;    //新数列的元素个数
        if(N%2==1) N++;
        List=new int[n];
        for(int i=0;i<n;i++)
            scanf("%d",&List[i]);
        sort(List,List+n);
        l = 0;
        r = List[n-1]-List[0];
        while (l < r)
        {
            //cout<<l<<' '<<r<<endl;
            P = (l+r) /2;
            tmp = 0;
            for (int j = 1; j < n; j++) //遍历j,寻找xj-xi<=P的个数
            {
                tmp = tmp + find(P, j);
                //cout<<tmp<<endl;
            }
            if (tmp < N/2)  //当计数小于n/2时。
                l=P+1;
            else    //当计数大于等于n/2时。
            {
                r=P;
            }
        }
        cout<<r<<endl;
    }
    return 0;
}
Published 8 original articles · Likes2 · Visits 252

Guess you like

Origin blog.csdn.net/lawrenceY/article/details/104980387