磁帶最大利用率問題——動態規劃
題目描述
設有n個程式{1,2,…,n}要存放在長度為L的磁帶上。程式i存放在磁帶上的長度是li,1<=i<=n.
程式儲存問題要求確定這n個程式在磁帶上的一個儲存方案,使得能夠在磁帶上儲存儘可能多的程式。在保證儲存最多程式的前提下,要求磁帶的利用率最大。
程式設計任務:對於給定的n個程式存放在磁帶上的長度,程式設計計算磁帶上最多可以儲存的程式數和佔用磁帶的長度。
輸入
第一行是2個正整數,分別表示檔案個數n和磁帶長度L。第二行中,有n個正整數,表示程式存放在磁帶上的長度。
輸出
第一行輸出最多可以儲存的程式數和佔用磁帶的長度;第二行輸出存放在磁帶上的每個程式的長度,(輸出程式次序應與輸入資料次序保持一致)
本來不想寫的部落格,無奈網上大部分程式碼都是貪心,就只將最後一個換成最大能容納的程式就是了。
給出
4 50
22 23 24 25
這個樣例很明顯就錯了。
這題應該是動態規劃:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include<algorithm>
#include<vector>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define pb push_back
#define G 6.67430*1e-11
#define rd read()
#define pi 3.1415926535
using namespace std;
const ll mod = 998244353;
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch>'9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
int dp[605][6005][2];
//dp[i][j][0]表示在程式數n、磁帶長度為j的情況下 ,最多可以儲存的程式數
// dp[i][j][1]表示在程式數n、磁帶長度為j的情況下 ,程式最多情況時的磁帶長度
int Count[605];
int pro_len[605];
int n, len;
int main() {
FILE* fp;
fp = fopen("input.txt", "r");
fscanf(fp, "%d %d", &n, &len);
for (int i = 1; i <= n; i++)
{
fscanf(fp, "%d", &pro_len[i]);
}
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= len; j++)
{
if (pro_len[i] <= j && dp[i - 1][j][0] < dp[i - 1][j - pro_len[i]][0] + 1)//第一個狀態轉移,如果個數更多則直接裝入,[i][j]=[i-1][j-pro_len[i]]
{
dp[i][j][0] = dp[i - 1][j - pro_len[i]][0] + 1;
dp[i][j][1] = dp[i - 1][j - pro_len[i]][1] + pro_len[i];
}
else if (pro_len[i] <= j && dp[i - 1][j][0] == dp[i - 1][j - pro_len[i]][0] + 1)//第二個狀態轉移,如果個數相同則取兩個狀態的max,[i][j]=max([i-1][j],[i-1][j-pro_len[i]])
{
dp[i][j][0] = dp[i - 1][j][0];
dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - pro_len[i]][1] + pro_len[i]);
}
else//否則直接繼承狀態
{
dp[i][j][0] = dp[i - 1][j][0];
dp[i][j][1] = dp[i - 1][j][1];
}
cout << dp[i][j][0] <<' ';
}
cout << endl;
}
cout << endl;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= len; j++)
{
cout << dp[i][j][1] << ' ';
}
cout << endl;
}
fp = fopen("output.txt", "w");
fprintf(fp, "%d %d\n", dp[n][len][0], dp[n][len][1]);
int j = dp[n][len][1], k = 1, i = n;
while (i)
{
if (j>=pro_len[i]&&i&&dp[i][j][0] == dp[i - 1][j - pro_len[i]][0] + 1 && dp[i][j][1]== dp[i - 1][j - pro_len[i]][1] + pro_len[i])
{
j -= pro_len[i];
Count[k++] = pro_len[i];
}
i--;
}
for (k = 1; k <= dp[n][len][0]; k++)
{
if (k != 1)fprintf(fp, " ");
fprintf(fp, "%d", Count[k]);
}
fprintf(fp, "\n");
return 0;
}
有點類似揹包問題,不過有三種狀態轉移的情況:
- 如果個數更多則直接裝入,[i][j]=[i-1][j-pro_len[i]]
- 如果個數相同則取兩個狀態的max,[i][j]=max([i-1][j],[i-1][j-pro_len[i]])
- 直接繼承狀態[i][j]=[i-1][j]
相關文章
- 動態規劃---例題3.最大子段和問題動態規劃
- 【動態規劃】揹包問題動態規劃
- 揹包問題----動態規劃動態規劃
- 動態規劃之子序列問題動態規劃
- 找零問題與動態規劃動態規劃
- 醜數問題——動態規劃、Java動態規劃Java
- 動態規劃 01揹包問題動態規劃
- 【動態規劃】01揹包問題動態規劃
- 動態規劃--01揹包問題動態規劃
- 動態規劃篇——揹包問題動態規劃
- 動態規劃-01揹包問題動態規劃
- 動態規劃之股票問題123動態規劃
- 動態規劃,股票問題留坑動態規劃
- 動態規劃最大欄位和動態規劃
- Leetcode 題解系列 -- 股票的最大利潤(動態規劃)LeetCode動態規劃
- 【動態規劃】01揹包問題【續】動態規劃
- 禮物的最大價值(一維動態規劃&二維動態規劃)動態規劃
- 動態規劃專題動態規劃
- 好題——動態規劃動態規劃
- 動態規劃題單動態規劃
- 0-1揹包問題(動態規劃)動態規劃
- 動態規劃,這幾個問題最常見!動態規劃
- 矩陣連乘問題 Python 動態規劃矩陣Python動態規劃
- 從“股票問題”談動態規劃問題的解決思路動態規劃
- leetcode題解(動態規劃)LeetCode動態規劃
- 動態規劃練習題動態規劃
- 動態規劃做題思路動態規劃
- 動態規劃解題方法動態規劃
- 動態規劃求解最長上升子序列問題動態規劃
- 動態規劃問題為什麼要畫表格?動態規劃
- 最小總和問題(動態規劃演算法)動態規劃演算法
- 動態規劃之0,1揹包問題動態規劃
- 動態規劃解0-1揹包問題動態規劃
- 動態規劃系列之六01揹包問題動態規劃
- 最長公共子序列問題—動態規劃sdut動態規劃
- 迴文串問題(動態規劃DP C++)動態規劃C++
- [LeetCode解題] -- 動態規劃二 [ 子串、子序列問題 ]LeetCode動態規劃
- 動態規劃 擺花 題解動態規劃