為敘述問題方便,現將任一選擇方案中,辯方總分和控方總分之差簡稱為「辯控差」,辯方總分和控方總分之和稱為「辯控和」。
第i 個候選人的辯方總分和控方總分之差記為v(i),辯方總分和控
方總分之和記為s(i)。現用f(j, k)表示,取j 個候選人,使其辯
控差為k 的所有方案中,辯控和最大的那個方案(該方案稱為「方
案f(j, k)」)的辯控和。並且,我們還規定,如果沒法選j 個人,
使其辯控差為k,那麼f(j, k)的值就為-1,也稱方案f(j, k)不可行。
本題是要求選出m 個人,那麼,如果對k 的所有可能的取值,求
出了所有的f(m, k) (-20×m≤ k ≤ 20×m),那麼陪審團方案
自然就很容易找到了。
問題的關鍵是建立遞推關係。需要從哪些已知條件出發,
才能求出f(j, k)呢?顯然,方案f(j, k)是由某個可行的方案f(j-1, x)
( -20×m ≤ x ≤ 20×m)演化而來的。可行方案f(j-1, x)能演化成
方案f(j, k)的必要條件是:存在某個候選人i,i 在方案f(j-1, x)中
沒有被選上,且x+v(i) = k。在所有滿足該必要條件的f(j-1, x)中,
選出 f(j-1, x) + s(i) 的值最大的那個,那麼方案f(j-1, x)再加上候選人i,
就演變成了方案 f(j, k)。這中間需要將乙個方案都選了哪些人都記錄下來。
不妨將方案f(j, k)中最後選的那個候選人的編號,記在二維陣列的
元素path[j][k]中。那麼方案f(j, k)的倒數第二個人選的編號,
就是path[j-1][k-v[path[j][k]]。假定最後算出了解方案的辯控差是k,
那麼從path[m][k]出發,就能順藤摸瓜一步步求出所有被選中的候選人。
初始條件,只能確定f(0, 0) = 0。由此出發,一步步自底向上遞推,
就能求出所有的可行方案f(m, k)( -20×m ≤ k ≤ 20×m)。實際解題
的時候,會用乙個二維陣列f 來存放f(j, k)的值。而且,由於題目中辯
控差的值k 可以為負數,而程式中數租下標不能為負數,所以,在程式中
不妨將辯控差的值都加上400,以免下標為負數導致出錯,即題目描述中,
如果辯控差為0,則在程式中辯控差為400。
#include#include#includeusing namespace std;
int n,m;
int dp[21][801];
int path[21][801];
/*回溯,確認dp[j][k]方案是否曾選擇過候選人i*/
bool select(int j,int k,int i,int* v)
return j?false:true;
}int main(void)
int fix=m*20; //總修正值,修正極限為從[-400,400]對映到[0,800]
dp[0][fix]=0; //由於修正了數值,因此dp[0][fix]才是真正的dp[0][0]
for(j=1;j<=m;j++)
for(k=0;k<=2*fix;k++)}}
}for(k=0;k<=fix;k++)
if(dp[m][fix-k]>=0 || dp[m][fix+k]>=0) //從中間向兩邊搜尋最小辨控差的位置k
break;
int div=dp[m][fix-k] > dp[m][fix+k] ? (fix-k):(fix+k); //最小辨控差
cout<<"jury #"
//辯方總值 = (辨控和+辨控差+修正值)/2
cout<<(dp[m][div]+div-fix)/2<<" for prosecution and value ";
//控方總值 = (辨控和-辨控差+修正值)/2
cout<<(dp[m][div]-div+fix)/2<<" for defence:"
for(i=0,j=m,k=div;isort(id,id+m); //公升序輸出候選人編號
for(i=0;icout<<' '
}
找工作挺難的
從lx走了,那是最後的一天,說來也奇怪,立馬病倒,發燒38.5整個人輕飄飄的,而且下半身感覺都不是自己的,算是是給自己放個假吧。415到915,也算是挺過來了,去不了好點的,那只能退而求其次,也算是知足吧。認識了,g和l,以及其他的人,都感覺算是自己的一種幸運,雖然技術上學到的東西不多,但是其他的事...
男人這輩子挺難的(好女人一定要看看)
男人這輩子挺難的 找個漂亮女人吧,太操心,找個不漂亮的吧,又不甘心 光顧事業了,人家說你沒責任感,光顧家了,人家又說你沒本事 專一點吧,人家說你不成熟 花心點吧,人家說你是禽獸 有錢,說你是壞人,沒有錢,人家罵你窩囊廢 自己奮鬥吧,等有錢了女友也老了,讓女人養吧,不如自宮練葵花寶典算了。不去應酬,怕...
GO語言的指標,挺難啃的一塊骨頭
眾所周知,在go語言中變數的宣告是為了在記憶體中先佔一塊記憶體空間,而指標變數就是指向這些記憶體空間的變數,理論上說它可以指向記憶體中任意乙個記憶體位址。宣告指標變數 var num int var floatnum float var cheo string 指向字串型別 var 指標變數名 所指...