第一題:
n個人,每個人有一個對應的技能值s,現在要從n個人中選出p個人,使得他們的技能值相同。
顯然,如果存在p個人的技能值是相同的,輸出0就可以了。如果不存在,就要找出p個人,對他們進行訓練,治他們的技能值相同。
訓練一個小時,技能值增加1,只有一個教練,也就是只能同時訓練一個 人。找出最佳的p個人的方案,輸出最小的訓練時間。
AC的代碼:
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
int s[100010]; // skill score
long long int t[100010];
int e[100010];
int main()
{
int tg;
scanf("%d", &tg);
int n, p;
int ca=1;
while(tg--) {
scanf("%d %d", &n, &p);
s[0] = 0;
for(int i=1; i<=n; i++) {
scanf("%d", &s[i]);
}
sort(s+1, s+n+1);
t[0] = 0;
for(int i=1; i<=n; i++) {
t[i] = t[i-1] + s[i];
}
for(int i=p; i<=n; i++) {
e[i] = t[i] - t[i-p];
}
int ans = s[p]*p - e[p];
int cur;
for(int i=p; i<=n; i++) {
cur = s[i]*p - e[i];
if(cur < ans)
ans = cur;
}
printf("Case #%d: %d\n", ca, ans);
ca++;
}
return 0;
}
第二題:
每次給你一個R*C的矩陣,矩陣的元素不是1就是0。1代表此處是一個郵局,0代表此處一個郵局,或者理解成是一個需要郵寄的用戶。
我們最多可以在某個為0的節點上再建立一個郵局,要輸出的是每種方案中所有的用戶到最近郵局的曼哈頓距離的最大值的最小值。
顯然,如果矩陣中都是1,都是郵局,輸出0就可以了(家門口就是郵局)。如果矩陣中存在0,顯然“最多可以建一次郵局”的機會必
須要用上,再多建立一個郵局,一定可以減小或者不變當前郵局布局下的曼哈頓的最大值中的最小值。
那這個郵局選擇在那個0的位置呢?最直接的方法就是枚舉,枚舉每個是0的位置,因為R和C的最大值是250。
但我寫的代碼貌似沒過較大的數據量的case。第一次參加kickstart,每台搞明白。
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;
struct node
{
int x, y;
int w;
}cur;
int main()
{
int tg;
scanf("%d", &tg);
int r, c;
int man_dis;
int ca=1;
vector<node>que1;
vector<node>que0;
while(tg--) {
que0.clear();
que1.clear();
scanf("%d %d", &r, &c);
char q[300][300];
for(int i=1; i<=r; i++) {
scanf("%s", q[i]);
for(int j=0; j<c; j++) {
cur.x = i;
cur.y = j+1;
if(q[i][j] == '1') {
que1.push_back(cur);
} else {
que0.push_back(cur);
}
}
}
int ans1 = 0;
for(int i=0; i<que0.size(); i++) {
int cur, mm=r+c+1;
for(int j=0; j<que1.size(); j++) {
cur = abs(que0[i].x - que1[j].x) + abs(que0[i].y - que1[j].y);
if(cur < mm)
mm = cur;
}
que0[i].w = mm;
if(mm > ans1)
ans1 = mm;
} // 找出所有普通節點的最小man距離, 找出這些距離里面的最大距離
if(que0.size() == 0) {
//
printf("Case #%d: 0\n", ca);
ca++;
} else {
int ans2 = 0;
int ans = r+c+1;
for(int i=0; i<que0.size(); i++) {
int x1 = que0[i].x;
int y1 = que0[i].y;
// 假設當前節點是郵局 更新最大的man距離
vector<int>mandis;
mandis.clear();
for(int j=0; j<que0.size(); j++) {
int x2 = que0[j].x;
int y2 = que0[j].y;
// int dis = abs(que0[i].x - que0[j].x) + abs(que0[i].y - que0[j].y);
int dis = abs(x1 - x2) + abs(y1 - y2);
if(dis < que0[j].w) {
mandis.push_back(dis);
} else {
mandis.push_back(que0[j].w);
}
}
ans2 = 0;
for(int j=0; j<mandis.size(); j++) {
if(i!=j && mandis[j] > ans2)
ans2 = mandis[j];
}
if(ans2 < ans)
ans = ans2;
}
printf("Case #%d: %d\n", ca, ans);
ca++;
}
}
return 0;
}
第三題:
n個座位,編號1---n,現在有q個預定,每次預定都是(L, R),如(1, 3)表示預定了1、2、3的位置。
由於每次的座位預定可能會存在重復的座位預定而導致沖突,現在讓你通過一種算法來實現保證每個預定的人
都能分到相同數量的k個座位,並保證這個k是最大的。沒想到好的算法,故沒有提交。(不過小數據量的情況下
暴力應該好過。依次枚舉每個座位,輪流分給有預定的人)。
沒有代碼!
