题目描述:Maximum Tape Utilization Ratio
设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。程序i存放在磁带上的长度是li ,1 < = i < = n。 程序存储问题要求确定这n 个程序在磁带上的一个存储方案,使得能够在磁带上存储尽可能多的程序。在保证存储最多程序的前提下还要求磁带的利用率达到最大。 对于给定的n个程序存放在磁带上的长度,编程计算磁带上最多可以存储的程序数和占用磁带的长度。
输入
第一行是2 个正整数,分别表示文件个数n <=600和磁带的长度L<=6000。接下来的1 行中,有n个正整数,表示程序存放在磁带上的长度。
输出
第1 行输出最多可以存储的程序数和占用磁带的长度;第2行输出存放在磁带上的每个程序的长度。
样例输入
9 50 2 3 13 8 80 20 21 22 23
样例输出
5 49 2 3 13 8 23
思路:先排序,最大可能存储程序的个数,然后DFS找到最优解。
备注:直接上来就DFS,一般般都会超时,用贪心策略才能A。
// Maximum Tape Utilization Ratio.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" //超时!!!!! //#include <stdio.h> //#include <string.h> //#include <algorithm> //#include <iostream> //using namespace std; // //#define MAX 605 //int n, len, L[MAX], maxL = 0 /*存储的最大长度*/, maxS = 0/*存储的最多程序数目*/, vis[MAX], path[MAX]; // //int cmp(int a, int b) //{ // return a < b; //} // ////DFS,index为当前处理的物品编号 ////sumS和sumL分别为当前总程序数和当前总长度 //void DFS(int index, int sumS, int sumL) //{ // if (sumL > len) return; // if (index >= n) // { //已经完成了对n件物品的选择(死胡同) // if (sumS > maxS || (sumS == maxS && maxL < sumL)) // { // maxS = sumS; // maxL = sumL; // memcpy(path, vis, sizeof(vis)); // } // return; // } // //岔道口 // vis[index]= 0 ; DFS(index + 1, sumS, sumL);//不选择第index件物品 // if ((len - sumL) >= L[index]) // vis[index] = 1; DFS(index + 1, sumS + 1, sumL + L[index]);//选择第index件物品 //} // //int main() //{ // scanf("%d %d", &n, &len); // for (int i = 0; i < n; i++) scanf("%d", &L[i]); // // memset(vis, 0, sizeof(vis)); // memset(path, 0, sizeof(path)); // // sort(L, L + n,cmp); // DFS(0, 0, 0); // // // //搜索背包路径 // int ans = 0, num = 0, res[MAX]; // for (int i = 0, flag = 0; i < n; i++) // { // if (path[i]) // { // ans += L[i]; // res[num++] = L[i]; // } // } // printf("%d %d\n", num,ans); // for (int i = 0; i < num;i++) // if (i != n - 1) printf("%d ", res[i]); // else printf("%d\n", res[i]); // // return 0; //} //超时解决方法:直接保存最优路径 //#include <stdio.h> //#include <algorithm> //#include <iostream> //using namespace std; // //#define MAX 605 //int n, len, L[MAX]; // //struct Path //{ // int num; // int len; // int p[MAX]; //}maxPath; // //int cmp(int a, int b) //{ // return a < b; //} // ////DFS,index为当前处理的物品编号 //void DFS(int index,Path cur) //{ // if (cur.len > len) return;//长度超了 // if ((cur.num + len - index) < maxPath.num) return;//即使是装了剩下的所有程序也无法成为最优 // if (index == n) // { //已经完成了对n件物品的选择 // if (cur.num > maxPath.num || (cur.num == maxPath.num && maxPath.len < maxPath.len)) // maxPath = cur; // return; // } // DFS(index + 1, cur);//不选择第index件物品 // // cur.p[cur.num++] = L[index];cur.len += L[index]; // DFS(index + 1, cur); // //} // //int main() //{ // while (scanf("%d %d", &n, &len)) // { // // for (int i = 0; i < n; i++) scanf("%d", &L[i]); // // sort(L, L + n, cmp); // // Path p; // p.len = 0; // p.num = 0; // DFS(0, p); // // printf("%d %d\n", maxPath.num, maxPath.len); // for (int i = 0; i < maxPath.num; i++) // if (i != n - 1) printf("%d ", maxPath.p[i]); // else printf("%d\n", maxPath.p[i]); // // } // // return 0; //} // //WA解决办法:保存排序索引 //#include <iostream> //#include <cstring> //#include <algorithm> //using namespace std; // //const int MAX = 605; //int n, len, L[MAX],ind[MAX]; // //struct Path //{ // int num; // int len; // int p[MAX]; // int inx[MAX]; // //}maxPath; // //void BubbleSort(int *p, int length, int * ind_diff) //{ // for (int m = 0; m < length; m++) // { // ind_diff[m] = m; // } // // for (int i = 0; i < length; i++) // { // for (int j = 0; j < length - i - 1; j++) // { // if (p[j] > p[j + 1]) // { // int temp = p[j]; // p[j] = p[j + 1]; // p[j + 1] = temp; // // int ind_temp = ind_diff[j]; // ind_diff[j] = ind_diff[j + 1]; // ind_diff[j + 1] = ind_temp; // } // } // } //} // ////DFS,index为当前处理的物品编号 //void DFS(int index, Path cur) //{ // if (cur.len > len) return;//长度超了 // if (index == n) // { //已经完成了对n件物品的选择 // if (cur.num > maxPath.num || (cur.num == maxPath.num && maxPath.len < maxPath.len)) // maxPath = cur; // return; // } // DFS(index + 1, cur);//不选择第index件物品 // // cur.p[cur.num] = L[index]; cur.len += L[index], cur.inx[cur.num++] = ind[index]; // DFS(index + 1, cur); // //} // //int cmp(int a, int b) //{ // return a < b; //} // //int main() //{ // while (cin>>n>>len) // { // // for (int i = 0; i < n; i++) cin >> L[i]; // // int *save = new int[MAX]; // memcpy(save, L, sizeof(L)); // // BubbleSort(L, n, ind); // // Path p; // p.len = 0; // p.num = 0; // DFS(0, p); // // cout << maxPath.num << " " << maxPath.len << endl; // // int *inx = new int[MAX]; // memcpy(inx, maxPath.inx, sizeof(maxPath.inx)); // // for (int i = 0; i < maxPath.num; i++) // if (i != maxPath.num - 1) cout << inx[i] << " "; // else cout << inx[i] << endl; // // sort(inx, inx + maxPath.num, cmp); // // for (int i = 0; i < maxPath.num; i++) // if (i != maxPath.num - 1) cout << save[inx[i]] << " "; // else cout << save[inx[i]] << endl; // // } // // return 0; //} //超时解决办法:换用贪心算法 //结果还是超时。。。。。 #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int MAX = 605; int n, len, L[MAX], save[MAX], mnum; struct Path { int num; int len; int p[MAX]; }maxPath; //DFS,index为当前处理的物品编号 void DFS(int index, Path cur, int remain) { if (cur.num == mnum) { //已经选择mnum件物品 if (cur.len > maxPath.len && cur.len <= len) maxPath = cur; return; } if (index >= n) return; if (cur.len + remain < maxPath.len) return; //if (cur.len + L[index] > len) return;这不应该加,如果加了大于len长度的不选和选择两种DFS都没有机会了,就丧失了不选之后的DFS遍历,结果就少了。 //至少不应该加在这里 DFS(index + 1, cur, remain - L[index]);//不选择第index件物品 if (cur.len + L[index] <= len) { cur.len += L[index]; cur.p[cur.num++] = L[index]; DFS(index + 1, cur, remain - L[index]); } } int cmp(int a, int b) { return a < b; } //arr,程序长度数组, r,已经使用程序的长度 int find_most(int arr[]) { sort(arr, arr + n, cmp); int i = 0, remain = len; for (; i < n; i++) { remain -= arr[i]; if (remain <= 0) return i; } return i; } void init(Path &a) { a.len = 0; a.num = 0; a.p[a.num] = { 0 }; } int main() { while (cin >> n >> len) { int remain = 0; for (int i = 0; i < n; i++) { cin >> L[i]; save[i] = L[i]; remain += L[i]; } //find most program number mnum = find_most(save); Path cur; init(cur); init(maxPath); //init && DFS DFS(0, cur, remain); //print ans cout << mnum << " " << maxPath.len << endl; for (int i = 0; i < maxPath.num; i++) if (i != maxPath.num - 1) cout << maxPath.p[i] << " "; else cout << maxPath.p[i] << endl; } return 0; }