2020.01.20刷題總結
技術標籤:創新創業預備役寒假學習每日總結
問題 F: 維斯頓的煩勞
描述
維斯頓經營著一個盜版販賣的商店(偶爾也會適應國家政策,擺地攤來擴大銷售)。當然大家都願意支援正版,可惜盜版生意依舊火爆,每次上貨基本就是被一搶而空。為此維斯頓不斷的擴大自己的商店,力求可以放下更多的商品,可惜現在手上的資金有限沒法擴容商店,為了最快速的獲得資金,那他就需要選擇那些利潤大的商品進行販賣。我們假設商店可以放下V體積的物品。維斯頓在上貨的時候有K件物品可以選擇,每件物品有體積(S),和利潤(P)兩個特徵。要在K件物品中選擇一些物品體積總和不超過V。使得利潤之和最大。格式
輸入格式
輸入一個浮點數 V(V<=1000,modf(V)>=0.01),和一個整數 K(k<=100)接著是K行,包含兩個浮點數S,P,(S<=V,P<=100,modf(S)>=0.01)輸出格式
輸出一個浮點數表示可以得到最大利潤之和。樣例
樣例輸入 Copy10 3
5 4
3 3
5 4樣例輸出 Copy
8.000000
典型的揹包問題,可是還是錯了好多。因為V是浮點數,所以不能用來當作下標,這樣一來就不能用記憶化陣列,當時我就想用set來索引,可是錯誤百出,因為對set不熟悉,下面是錯誤的程式碼:
#include <bits/stdc++.h>
using namespace std;
struct node
{
float v = 0, p = 0;
};
node a[110];
float v;
int k;
float max(float a, float b)
{
return a > b ? a : b;
}
struct ans
{
int i;
float v;
float ansr;
bool operator<(const ans &a) const
{
if (this->i == a.i && this->v == a.v)
return false;
else
return true;
}
};
set<ans> mem;
float solove(int i, float v)
{
ans t = {i, v};
if (mem.count(t))
return mem.find(t)->ansr;
if (i == k)
return 0;
t.i = i, t.v = v;
if (v < a[i].v)
t.ansr = solove(i + 1, v);
else
t.ansr = max(solove(i + 1, v), solove(i + 1, v - a[i].v) + a[i].p);
mem.insert(t);
return t.ansr;
}
int main(void)
{
cin >> v >> k;
for (int i = 0; i < k; i++)
cin >> a[i].v >> a[i].p;
printf("%lf", solove(0, v));
//cout<<solove(0,v);
return 0;
}
後來仔細看題,發現一個東西:modf(V)>=0.01
!!!我可以把V*100,這樣不就可以轉換成整數了嘛,最後ans/100不就行了,早看到這個也不會讓我瞎琢磨那麼久了(仔細審題很重要)。
下面是AC程式碼:
#include <bits/stdc++.h>
using namespace std;
double max(double a, double b)
{
return a > b ? a : b;
}
struct obj
{
int s;
double p;
};
int main(void)
{
double t;
int v, k;
obj a[110];
double dp[110000] = {0};
cin >> t >> k;
v = t * 100;
for (int i = 1; i <= k; i++)
{
cin >> t >> a[i].p;
a[i].s = t * 100;
}
for (int i = 1; i <= k; i++)
for (int j = v; j > 0; j--)
if (j >= a[i].s)
dp[j] = max(dp[j], dp[j - a[i].s] + a[i].p);
printf("%lf\n", dp[v]);
return 0;
}
問題 A: 切繩子
描述
有n條繩子,長度分別為L[i]。如果從他們中切割出k條長度相同的繩子的話,這k條繩子每條最長能有多長?(答案保留小數點後兩位(直接舍掉兩位後的小數),規定1單位長度的繩子最多可以切割成100份)格式
輸入格式
包含多組輸入
輸入n,k,(1<=n,k<=10000)
然後n行,輸入L[i],代表每一條繩子的長度(1<=L[i]<=100000)輸出格式
切出k條長度相等的繩子最大長度是多少,輸出保留兩位小數樣例
樣例輸入 Copy
4 11
8.02
7.43
4.57
5.39
樣例輸出 Copy
2.00
這題其實簡單,但是犯了一個非常粗心的錯誤,沒有把double轉換成int,所以結果有問題:
bool check(double ans)
{
int count = 0;
for (int i = 0; i < n; i++)
count += (int)L[i] / ans;
if (count >= k)
return true;
return false;
}
改完之後:
bool check(double ans)
{
int count = 0;
for (int i = 0; i < n; i++)
count += (int)L[i] /(int)ans;
if (count >= k)
return true;
return false;
}
AC程式碼:
#include <bits/stdc++.h>
#define INF ((unsigned(-1)) >> 1)
using namespace std;
const int maxn = 10010;
int n, k;
double L[maxn];
bool check(double ans)
{
int count = 0;
for (int i = 0; i < n; i++)
count += (int)L[i] / (int)ans;
if (count >= k)
return true;
return false;
}
int main(void)
{
while (cin >> n >> k)
{
double l = 0, r = INF, mid = (l + r) / 2, ans = 0;
for (int i = 0; i < n; i++)
{
cin >> L[i];
L[i] *= 100;
}
while (l <= r)
{
if (check(mid))
{
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
mid = (l + r) / 2;
}
printf("%.2lf\n", ans / 100);
}
return 0;
}
問題 B: 如何放牛
描述
農夫有n個牛欄,m頭牛,然後要讓你把m個牛都放進牛欄裡,讓兩頭牛之前的最大的最小距離格式
輸入格式
多組輸入
輸入n,m (1<=m<=n<=100000)
下面n行是牛欄的位置xi (0 <= xi <=1,000,000,000)輸出格式
輸出兩頭牛最大的最小距離樣例
樣例輸入 Copy
5 3
1
2
8
4
9
樣例輸出 Copy
3提示
FJ可以將他的3頭奶牛放在位置1,4和8的攤位上,最小距離為3.大量輸入資料,建議使用scanf。
就如題目提示一樣,我用cin超時了。還有就是,check函式想當然的去寫,結果錯了,後來排查半天才出來。哎,菜是原罪。
這是錯誤的check:
bool check(int mid)
{
int count = 0;
int begin = 0, end = 1;
while (end < n)
{
while (end < n && x[end] - x[begin] < mid)
end++;
if (x[end] - x[begin] >= mid)
count++;
else
return false;
begin = end, end = end + 1;
}
if (count >= m)
return true;
return false;
}
我以為 if (x[end] - x[begin] >= mid)
滿足的話,說明end已經大於等於n了,可是沒考慮到end等於n的時候,越界後x[end]的結果未知,所以if的成立也未知,然後就WA了。
改之後的程式碼:
bool check(int mid)
{
int count = 1;
int begin = 0, end = 1;
while (end < n)
{
while (end < n && x[end] - x[begin] < mid)
end++;
if (end < n && x[end] - x[begin] >= mid)
count++;
begin = end, end = end + 1;
}
if (count >= m)
return true;
return false;
}
AC程式碼:
#include <bits/stdc++.h>
typedef unsigned long long ull;
#define INF ((unsigned(-1)) >> 1)
const int maxn = 100100;
ull x[maxn];
int n, m;
using namespace std;
bool check(int mid)
{
int count = 1;
int begin = 0, end = 1;
while (end < n)
{
while (end < n && x[end] - x[begin] < mid)
end++;
if (end < n && x[end] - x[begin] >= mid)
count++;
begin = end, end = end + 1;
}
if (count >= m)
return true;
return false;
}
int main(void)
{
while (cin >> n >> m)
{
for (int i = 0; i < n; i++)
scanf("%llu", x + i);
sort(x, x + n);
int l = 0, r = INF, mid = (l + r) / 2, ans = 0;
while (l <= r)
{
if (check(mid))
{
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
mid = (l + r) / 2;
}
cout << ans << endl;
}
return 0;
}