SDOI
一年一度的全國信息學奧林匹克競賽(NOI)即將舉辦,SD省組織進行了一次省隊選拔,一共有 n(n≤100)名選手參加了這次省隊選拔。 今年,SD省的省隊名額爲 m(m≤50) 人,即,今年的SD省隊有 m 名隊員。 按照慣例,SD省的省隊選拔有兩輪比賽,依次爲“Round1”和“Round2”,每個Round的滿分爲 300 分。 所有 n 名選手都參加了Round1和Round2,現在每名選手Round1和Round2的“原始得分”已經確定。SD省的省隊選拔採用標準分計算方式,即,設某個Round的最高原始得分爲 x 分(保證每輪比賽都不會全場零分,即x>0),那麼此Round每名選手的“相對得分”爲: 這名選手此Round的原始得分∗(300/x)。 所有選手的Round1和Round2的相對得分計算完畢後,將計算每名選手的“最終成績”。一名選手的最終成績爲:這名選手的Round1相對得分∗0.3 + 這名選手的Round2相對得分∗0.7。非常和諧的是,保證不存在兩名選手的最終成績相等。 所有選手的最終成績計算完畢後,將會按照以下規則選出省隊隊員: 爲了鼓勵女生參加信息學奧賽及相關活動,在有女選手參加省隊選拔的情況下,省隊中有一個固定的女選手名額。 1)若沒有女選手參加省隊選拔,則最終成績最高的 m 位選手進入省隊。 2)若有女選手參加省隊選拔,則最佳女選手(女選手中最終成績最高者)進入省隊,其餘的選手(男選手和最佳女選手之外的女選手)中成績最高的 m−1 位選手進入省隊。 現在已經到了省隊選拔的最後階段,請你編寫一個程序,根據輸入的所有選手的信息(姓名,性別,Round1和Round2的原始得分),輸出進入省隊的選手的姓名,輸出的姓名按照省隊隊員的最終成績降序(從高到低)排列。
第一行爲一個整數 T(T≤100),表示數據組數。 接下來有T組數據。 對於每組數據,第一行有兩個正整數 n 和 m(n≥m),分別表示參加省隊選拔的選手人數和省隊的名額數。接下來有 n 行,每行輸入一名選手的信息,共4項,依次爲姓名(一個長度不超過20的字符串,只包含數字和大小寫英文字母)、性別(一個字符串,爲"male"[男]或"female"[女])、Round1原始得分(小於等於300的非負整數)和Round2原始得分(小於等於300的非負整數)。各項之間用空格隔開。
對於每組數據,先輸出一行"The member list of Shandong team is as follows:"(不帶引號),接下來輸出m行,每行爲一名省隊隊員的姓名,按省隊隊員的最終成績降序(從高到低)排列。
2 10 8 dxy male 230 225 davidwang male 218 235 evensgn male 150 175 tpkuangmo female 34 21 guncuye male 5 15 faebdc male 245 250 lavender female 220 216 qmqmqm male 250 245 davidlee male 240 160 dxymeizi female 205 190 2 1 dxy male 300 300 dxymeizi female 0 0
The member list of Shandong team is as follows: faebdc qmqmqm davidwang dxy lavender dxymeizi davidlee evensgn The member list of Shandong team is as follows: dxymeizi
第一組數據:第一輪最高分爲250,所以每個人的成績都要乘(300/250)=1.2,第二輪最高分也爲250,每個人的成績也要乘1.2。 每個人的最終成績按降序排如下 faebdc 298.20 qmqmqm 295.80 davidwang 275.88 dxy 271.80 lavender 260.64 dxymeizi 233.40 davidlee 220.80 evensgn 201.00 tpkuangmo 29.88 guncuye 14.40 有女選手參加,最佳女選手lavender進入省隊,其他分最高的7人按名次排列進入省隊 第二組數據:有女選手參加,最佳女選手dxymeizi進入省隊,dxy雖然分高,但不能進隊。
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=105;
struct Node
{
string name;
string x;
int r1,r2;
double temp1,temp2,sum;
};
Node peo[MAXN];
bool cmp(Node a,Node b)
{
return a.sum>b.sum;
}
int main()
{
int t,n,m;
cin>>t;
while(t--)
{
int g=0,x1=0,x2=0;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>peo[i].name;
cin>>peo[i].x;
if(peo[i].x=="female")
{
g++;
}
cin>>peo[i].r1;
x1=(x1>peo[i].r1?x1:peo[i].r1);
cin>>peo[i].r2;
x2=(x2>peo[i].r2?x2:peo[i].r2);
}
for(int i=0;i<n;i++)
{
peo[i].temp1=peo[i].r1*(300/(x1*1.0));
peo[i].temp2=peo[i].r2*(300/(x2*1.0));
peo[i].sum=peo[i].temp1*0.3+peo[i].temp2*0.7;
}
sort(peo,peo+n,cmp);
cout<<"The member list of Shandong team is as follows:"<<endl;
if(g>0)
{
int index;
for(int i=0;i<n;i++)
{
if(peo[i].x=="female")
{
index=i;
break;
}
}
if(index>=m)
{
for(int i=0;i<m-1;i++)
{
cout<<peo[i].name<<endl;
}
cout<<peo[index].name<<endl;
}
else
{
for(int i=0;i<m;i++)
{
cout<<peo[i].name<<endl;
}
}
}
else
{
for(int i=0;i<m;i++)
{
cout<<peo[i].name<<endl;
}
}
}
return 0;
}
Reorder the Books
dxy家收藏了一套書,這套書叫《SDOI故事集》,《SDOI故事集》有n(n≤19)本,每本書有一個編號,從1號到n號。 dxy把這些書按編號從小到大,從上往下摞成一摞。dxy對這套書極其重視,不允許任何人動這套書。 有一天Evensgn到dxy家玩,dxy因爲和妹子有約會,就讓Evensgn自己待在他家。Evensgn對這套書非常好奇,偷偷的看了一下,結果發現這裏面竟然有當年小E和小Q的故事。Evensgn看得出神,結果把一摞書的順序打亂了。 眼看着dxy就要回來了,Evensgn需要儘快把這摞書恢復到原先排好序的狀態。由於每本書都非常重,所以Evensgn能做的操作只有把一本書從書堆中抽出來,然後把這本書放到書堆的頂部。 給你打亂的書的順序,你能幫Evensgn算算最少需要幾次上述的操作,他才能把這套書恢復順序?假如你能算出來的話,Evensgn答應送給你一本他簽名的書《SDOI故事集9:小E的故事》
輸入包含多組數據。 第一行包含一個正整數T(T≤30)表示數據組數。 對於每組數據,第一行爲一個正整數n表示這套《SDOI故事集》中有多少本書。 接下來一行n個用空格分開的正整數,表示Evensgn打亂後的這摞書的書號順序(從上往下)。
對於每組數據,輸出一行一個整數,表示Evensgn最少需要幾次操作才能講書恢復順序。
2 4 4 1 2 3 5 1 2 3 4 5
3 0
對於第一組數據,我們先把3號書放到最上面,接着操作2號書,最後操作1號書,(4,1,2,3)→(3,4,1,2)→(2,3,4,1)→(1,2,3,4),這樣就有序了 對於第二組數據,這摞書本來就有序了,所以不需要任何操作 n>15的數據不超過10組
如果匹配不成功,開始序列向前移動,如果匹配成功,最終順序向前移動(即是匹配其前一個)。
使得儘量多可以匹配到。最終剩下的未被匹配的元素依次移動到隊頭,就可以以最少的步數
到達最終順序。
#include<iostream>
using namespace std;
const int MAXN = 25;
int book[MAXN];
int main()
{
int t, n;
cin >> t;
while (t--)
{
int i, j;
cin >> n;
for (i = 1; i <= n; i++)
{
cin >> book[i];
}
for (i = j = n; i > 0; i--)
{
if (book[i] == j)
{
j--;
}
}
cout << j << endl;
}
//system("pause");
return 0;
}
The Highest Mark
2045年的SD省隊選拔,賽制和三十年前已是完全不同。一場比賽的比賽時間有 t 分鐘,有 n 道題目。 第 i 道題目的初始分值爲 Ai(Ai≤106) 分,之後每過一分鐘這道題目的分值會減少 Bi 分,並且保證到比賽結束時分值不會減少爲負值。比如,一個人在第 x 分鐘結束時做出了第 i 道題目,那麼他/她可以得到 Ai−Bi∗x 分。 若一名選手在第 x 分鐘結束時做完了一道題目,則他/她可以在第 x+1 分鐘開始時立即開始做另一道題目。 參加省隊選拔的選手 dxy 具有絕佳的實力,他可以準確預測自己做每道題目所要花費的時間,做第 i 道需要花費 Ci(Ci≤t) 分鐘。由於 dxy 非常神,他會做所有的題目。但是由於比賽時間有限,他可能無法做完所有的題目。他希望安排一個做題的順序,在比賽結束之前得到儘量多的分數。
第一行爲一個正整數 T(T≤10),表示數據組數(n>200的數據不超過5組)。 對於每組數據,第一行爲兩個正整數 n(n≤1000) 和 t(t≤3000), 分別表示題目數量和比賽時間。接下來有 n 行,每行 3 個正整數依次表示 Ai,Bi,Ci,即此題的初始分值、每分鐘減少的分值、dxy做這道題需要花費的時間。
對於每組數據輸出一行一個整數,代表dxy這場比賽最多能得多少分
1 4 10 110 5 9 30 2 1 80 4 8 50 3 2
88
dxy先做第二題,再做第一題,第一題得分爲110−5∗(1+9)=60,第二題得分爲30−2∗1=28,總得分爲88,其他任何方案的得分都小於88
思路:貪心+DP,剛開始按照每題解決時間來貪心【按c遞增排序】,初始AC了,但是終判WA了,看了題解發現按每道題目扣分速度與做題時間的比值排序,按照比值從大到小做題。
首先我們考慮,假如我們已經確定了要做哪些題目,按什麼順序做這些題目最好。
假設已經確定了要做其中的m道題,某一個方案中做題的順序是依次做x1,x2→xm,那麼對於這個方案中任意的相鄰兩項xi,xi+1,考慮交換這兩項的順序,方案是否會變得更優,交換方案中的相鄰兩項,只會對這兩道題的得分有影響,對其餘的題目不會產生影響。
如果不交換這兩項,損失的分數是 Cxi∗Bxi+1+K,如果交換這兩項,損失的分數是Cxi+1∗Bxi+K (K是一個常數) 所以只需要判斷是否 Cxi∗Bxi+1≤Cxi+1∗Bxi+K,如果此不等式成立,那麼應該交換這兩項。對上式移項得 Bxi+1/Cxi+1>Bxi/Cxi 。所以對於一個確定的題目集合,做題的最優順序只與每道題目的Bi/Ci有關,按每道題目扣分速度與做題時間的比值排序,按照比值從大到小做題。
因此我們先對所有的題目按照這個比值進行排序,接下來,只要按照排好的順序,選擇做哪些題目就可以了。這相當於一個簡單的“揹包問題”,使用動態規劃來解決。dpi表示恰好用了i分鐘的最高得分。狀態轉移方程爲dpi=max1≤j≤ndpi−Cj+Aj−(i∗Bj)。
最終答案是max0≤i≤tdpi。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1010;
const int MAXT = 3010;
struct Node
{
int a, b, c;
double s;
};
Node pos[MAXN];
int dp[MAXT];
bool cmp(Node a, Node b)
{
return a.s>b.s;
}
int my_max(int a, int b)
{
return a>b ? a : b;
}
int main()
{
int ans, n, t;
cin >> ans;
while (ans--)
{
cin >> n >> t;
for (int i = 0; i < n; i++)
{
cin >> pos[i].a >> pos[i].b >> pos[i].c;
pos[i].s = (pos[i].b*1.0) / pos[i].c;
}
sort(pos, pos + n, cmp);
memset(dp, 0, sizeof(dp));
for (int i = 0; i<n; i++)
{
for (int j = t; j >= pos[i].c; j--)
{
dp[j] = my_max(dp[j], dp[j - pos[i].c] + my_max(0,(pos[i].a - pos[i].b*j)));
}
}
int total = 0;
for (int i = 0; i <= t; i++)
{
total = my_max(total,dp[i]);
}
cout << total << endl;
}
//system("pause");
return 0;
}