A group of tourists is going to kayak and catamaran tour. A rented lorry has arrived to the boat depot to take kayaks and catamarans to the point of departure. It's known that all kayaks are of the same size (and each of them occupies the space of 1 cubic metre), and all catamarans are of the same size, but two times bigger than kayaks (and occupy the space of 2 cubic metres).
Each waterborne vehicle has a particular carrying capacity, and it should be noted that waterborne vehicles that look the same can have different carrying capacities. Knowing the truck body volume and the list of waterborne vehicles in the boat depot (for each one its type and carrying capacity are known), find out such set of vehicles that can be taken in the lorry, and that has the maximum total carrying capacity. The truck body volume of the lorry can be used effectively, that is to say you can always put into the lorry a waterborne vehicle that occupies the space not exceeding the free space left in the truck body.
The first line contains a pair of integer numbers n and v (1 ≤ n ≤ 105; 1 ≤ v ≤ 109), where n is the number of waterborne vehicles in the boat depot, and v is the truck body volume of the lorry in cubic metres. The following n lines contain the information about the waterborne vehicles, that is a pair of numbers ti, pi (1 ≤ ti ≤ 2; 1 ≤ pi ≤ 104), where ti is the vehicle type (1 – a kayak, 2 – a catamaran), and pi is its carrying capacity. The waterborne vehicles are enumerated in order of their appearance in the input file.
In the first line print the maximum possible carrying capacity of the set. In the second line print a string consisting of the numbers of the vehicles that make the optimal set. If the answer is not unique, print any of them.
3 2
1 2
2 7
1 3
7
2
解题思路:设t=1的载具为a,t=2的载具为b。
将a和b的两种载具存储在两个数组nua,nub里面,长度分别为lea,leb,按p从大到小排序。
如果v是奇数则减一(如果lea不为0,从nua中选出第一个,我是为了方便后面两个a与一个b的比较)
否则进入循环,将两个a与一个b的元素进行比较。
最后如果还剩下1v,则补上一个a。
(代码写的好乱啊)
这题有个数据坑了我好久。
3 1
2 1
2 2
2 3
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <cmath> 6 using namespace std; 7 const int maxn = 100005; 8 struct nod { 9 int num; 10 int p; 11 }nua[maxn],nub[maxn]; 12 bool cmp(nod a,nod b) { 13 if(a.p>b.p) return 1; 14 return 0; 15 } 16 int pu[maxn]; 17 string s; 18 int main() { 19 ios::sync_with_stdio(false); 20 int n,v; 21 cin>>n>>v; 22 int lea=0,leb=0,cnt=0; 23 for(int i=1;i<=n;i++) { 24 int a,b; 25 cin>>a>>b; 26 if(a==1) { 27 nua[++lea].p=b; 28 nua[lea].num=i; 29 } 30 else { 31 nub[++leb].p=b; 32 nub[leb].num=i; 33 } 34 } 35 sort(nua+1,nua+lea+1,cmp); 36 sort(nub+1,nub+leb+1,cmp); 37 int i=1,j=1; 38 int ans=0; 39 if(lea && (v&1)) { 40 --v; 41 pu[++cnt]=nua[i].num; 42 ans+=nua[i++].p; 43 // cout<<1<<endl; 44 } 45 // cout<<v<<endl<<endl;; 46 while(i<=lea&&v>0) { 47 int u=nua[i].p+nua[i+1].p; 48 if(u>=nub[j].p) { 49 ans+=u; 50 pu[++cnt]=nua[i].num; i++; 51 if(i<=lea) { 52 pu[++cnt]=nua[i].num; 53 i++; 54 } 55 56 } 57 else { 58 ans+=nub[j].p; 59 pu[++cnt]=nub[j].num; 60 // cout<<2<<endl; 61 j++; 62 } 63 v-=2; 64 } 65 while(j<=leb&&v>1) { 66 ans+=nub[j].p; 67 pu[++cnt]=nub[j].num; 68 j++; 69 v-=2; 70 } 71 cout<<ans<<endl; 72 for( i=1;i<=cnt;i++) cout<<pu[i]<<" "; 73 return 0; 74 }
因为上面我的思路太乱了,第二天我看了看别人的思路,重做此题。
新思路:设t=1的载具为a,t=2的载具为b.依然分成nua,nub两组,按p从大到小排序。从大到小,能放多少b就放多少,如果v还有剩余,就放a。
然后把放进去的b载具从小到大遍历,每一个b与每两个a的p的和作比较,如果两a之和大于b,就更新此处。
思路很简单,代码也很好模拟。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <cmath> 6 using namespace std; 7 const int maxn = 100005; 8 struct nod { 9 int num; 10 int p; 11 }nua[maxn],nub[maxn]; 12 bool cmp(nod a,nod b) { 13 if(a.p>b.p) return 1; 14 return 0; 15 } 16 int pu[maxn]; 17 string s; 18 int main() { 19 ios::sync_with_stdio(false); 20 int n,v; 21 cin>>n>>v; 22 int lea=0,leb=0,cnt=0; 23 for(int i=1;i<=n;i++) { 24 int a,b; 25 cin>>a>>b; 26 if(a==1) { 27 nua[++lea].p=b; 28 nua[lea].num=i; 29 } 30 else { 31 nub[++leb].p=b; 32 nub[leb].num=i; 33 } 34 } 35 sort(nua+1,nua+lea+1,cmp); 36 sort(nub+1,nub+leb+1,cmp); 37 38 int i=1,j=1; 39 int ans=0; 40 while(j<=leb && v>=2) { //先存t=2的载具 41 v-=2; 42 j++; 43 } 44 while(i<=lea && v>=1) { //v有剩余,就存t=1 45 --v; 46 i++; 47 } 48 int l=0; //记录有哪些个b被取代 49 for(int k=j-1;k>=1;k--) { //放进去的b从小到大遍历 50 int u=nua[i].p+nua[i+1].p; 51 if(u>nub[k].p) { //每两个a与一个b比较 52 if(i+1<=lea) { 53 i+=2; 54 } 55 else { 56 ++i; 57 break; 58 } 59 ++l; 60 } 61 } 62 j-=l; 63 for(int k=1;k<j;k++) { 64 ans+=nub[k].p; 65 pu[++cnt]=nub[k].num; 66 } 67 for(int k=1;k<i;k++) { 68 ans+=nua[k].p; 69 pu[++cnt]=nua[k].num; 70 } 71 sort(pu+1,pu+cnt+1); 72 cout<<ans<<endl; 73 for(int i=1;i<=cnt;i++) { 74 cout<<pu[i]<<" "; 75 } 76 return 0; 77 }