WEEK4 二分和貪心

2021-10-04 04:12:07 字數 3876 閱讀 9224

zjm 有 n 個作業,每個作業都有自己的 ddl,如果 zjm 沒有在 ddl 前做完這個作業,那麼老師會扣掉這個作業的全部平時分。

所以 zjm 想知道如何安排做作業的順序,才能盡可能少扣一點分。

請你幫幫他吧!

輸入包含t個測試用例。輸入的第一行是單個整數t,為測試用例的數量。

每個測試用例以乙個正整數n開頭(1<=n<=1000),表示作業的數量。

然後兩行。第一行包含n個整數,表示ddl,下一行包含n個整數,表示扣的分。

對於每個測試用例,您應該輸出最小的總降低分數,每個測試用例一行。

首先吧,咱建立乙個結構體,用於儲存每個作業的分值和ddl。(因為不用說出具體的順序,序號什麼的就不管了)

然後輸入所有的作業情況後,我們要幹的就是把所有的作業按照分值的大小,由高往低排列。一樣分值的再按照ddl小的進行排列。

排列完成後,按照這個順序,挨個對作業進行處理,假設第m個任務的ddl為x,那麼就優先把這個作業排在x那一天。如果那一天已經被其他作業占用,就往前找,找到乙個小於ddl又是空閒的天數,確定下來。如果已經找不到小於ddl且空閒的天數,那麼這個作業就捨棄掉,它的分值就加入到減少的分裡面去。重複此操作,直到所有能安排的作業都已經安排好,即可。

#include

using

namespace std;

#include

struct work

;bool

cmp(work& a,work& b)

int vis[

1000];

int n;

void

innitial()

bool

insert

(int ddl)

if(vis[i]==0

&&i>=1)

else

return

false;}

intmain()

for(

int i=

0;i)sort

(works,works+n,cmp)

;innitial()

;for

(int i=

0;i) cout<}return0;

}

對於陣列的迴圈處理時,陣列的端點還是沒有處理的太好,都是後來拿資料試才找到究竟該怎麼寫。

zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。

當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。

請你幫幫他吧!

第一行:n(代表數列中數字的個數) (1≤n≤4000)

接下來的 n 行中,第 i 行有四個數字,分別表示數列 a,b,c,d 中的第 i 個數字(數字不超過 2 的 28 次方)

輸出不同組合的個數。

首先先遍歷a,b陣列,把他們的值相加,存到另乙個陣列裡面去。

然後再給那個陣列排個序。

遍歷c,d陣列,使用二分法在上面存放a+b的結果的陣列裡尋找-(c+d)(用left,mid,right,三個點來迴圈尋找改點第一次出現的時候,以及最後一次出現的時候)累加差值即可。

接下來詳細的說一說這個讓我頭疼的二分法:

先取left和right的值,即存放a+b結果的那個陣列的最左端和最右端。mid就是他們兩個的中值。用mid來和要尋找的數作比較,因為我們這個是乙個公升序的陣列,於是比mid大就在右邊,就在mid,right的範圍內再來一次二分。反之就是在left,mid的範圍內再來一次二分。

而當尋找的數就是mid的時候,操作就有所不同了。

尋找第一次出現的時候,當mid=shu,我們就繼續往mid的右邊找,因為右邊可能還有和數相等的數,前面有數就代表著這個mid所代表的數不是第乙個出現的shu。就需要我們繼續往右邊找。

而找到最後一次出現的數的時候,結果就剛好相反,也是一樣的思路。當mid=shu,很有可能mid的右邊還有和shu相等的數,不一定mid就是最後乙個出現的數,所以還需要往左找。

一當出現相等的數,就記錄答案,再次出現相等的數,就更新答案,簡單來說就是這樣。

#include

using

namespace std;

#include

int step=0;

int*a,

*b,*c,

*d;int

*all;

int n;

intfind_back

(int shu)

else

if(all[mid]

>shu)

else left=mid+1;

//cout<<"front left="<}

return ans;

}int

find_front

(int shu)

else left=mid+1;

}return ans;

}bool

cmp(

int f,

int b)

intmain()

for(

int i=

0;isort

(all+

1,all+n*n+

1,cmp)

;//for(int i=1;i<=n*n;i++)

//cout(int i=

0;icout

}

最開始以為自己懂了,寫了半天發現還是n的4次方的複雜度。然後又多看了半天才理解到二分的用法。害,還是不太熟

tt 是一位重度愛貓人士,每日沉溺於 b 站上的貓咪頻道。

有一天,tt 的好友 zjm 決定交給 tt 乙個難題,如果 tt 能夠解決這個難題,zjm 就會買乙隻可愛貓咪送給 tt。

任務內容是,給定乙個 n 個數的陣列 cat[i],並用這個陣列生成乙個新陣列 ans[i]。新陣列定義為對於任意的 i, j 且 i != j,均有 ans = abs(cat[i] - cat[j]),1 <= i < j <= n。試求出這個新陣列的中位數,中位數即為排序之後 (len+1)/2 位置對應的數字,』/』 為下取整。

tt 非常想得到那只可愛的貓咪,你能幫幫他嗎?

多組輸入,每次輸入乙個 n,表示有 n 個數,之後輸入乙個長度為 n 的序列 cat, cat[i] <= 1e9 , 3 <= n <= 1e5

輸出新陣列 ans 的中位數

這道題的資料十分龐大,所以必須要使用二分法來減少運算量。

先輸入所有資料到陣列裡,然後對陣列進行排序操作。

我就設定了,small,large來表示a[j]-a[i]的最小值和最大值。mid代表他們的中值,是用來估計新的數列的中位數的大小的。

然後就是每次的mid就採用,a[j]-a[i]#include

#include

#include

using

namespace std;

int n;

int a[

100005];

intfindcnt

(int i,

int xi_p)

return l -

(i+1);

}bool

judge

(int p,

int index)

// x的名次小於index則返回1, 反之返回0

return sum < index;

}int

find

(int index)

return l;

}int main (

)return0;

}我這個**還有一些問題,在和其他同學交流過後,我才意識到,在尋找有多少個a[j]-a[i]還有我的方法記錄了小於它的數和等於它的數,在名次的計算上那個值就不直接是名次,還需要做一些轉換才行。

week4作業 B二分

對於這道題,乙個顯然的四重迴圈o n4 的暴力做法顯然會超時,資料量為4e4,於是考慮如下優化 將兩個數列的組合看成一組新數列,那麼我們就可以得到兩個n2的數列,首先對其中乙個數列排序,分別對於乙個數列中的所有元素的相反數,在另一組有序數列中二分找到相應的元素 a b c d b 四個數列 zjm ...

week4 二分 中位數

title 任務內容是,給定乙個 n 個數的陣列 cat i 並用這個陣列生成乙個新陣列 ans i 新陣列定義為對於任意的 i,j 且 i j,均有 ans abs cat i cat j 1 i j n。試求出這個新陣列的中位數,中位數即為排序之後 len 1 2 位置對應的數字,為下取整。in...

week4 二分 四個數列

title zjm 有四個數列 a,b,c,d,每個數列都有 n 個數字。zjm 從每個數列中各取出乙個數,他想知道有多少種方案使得 4 個數的和為 0。當乙個數列中有多個相同的數字的時候,把它們當做不同的數對待。input 第一行 n 代表數列中數字的個數 1 n 4000 接下來的 n 行中,第...