先贴上错误代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
int v[4]={};
for(int i=0;i<4;i++)//读入数据
cin>>v[i];
bool flag=true;//用于判断是否还有三种不同类型的
int ans=0;
while(flag)
{
int cnt=0;//记录减少的数
for(int i=0;i<4;i++)//读入数据
if(v[i]>0&&cnt<3)v[i]--,cnt++;//将食物份数--,将记录数++
if(cnt!=3)flag=false;//若不足三份食物则退出循环
else ans++;//若达到3次则增加人数
}
cout<<ans<<endl;
}
return 0;
}
分析:
*此解法为错误解法
* 在2 3 3 4时,输出3,正确答案为4,第一次1 2 3 3 第二次 1 2 2 2 第三次 1 1 1 1第四次0 0 0 1
* 而本解为第一次1 2 2 4 第二次0 1 1 4第三次 0 0 0 3,第四份食物没有充分利用
* 由于取用食物的随机性,此解法可能会将少的先取完,而不用到最多的那份,导致多的用不上
* 而事实上我们应该尽量用多份数的食物,应该用到排序
* 解法一:先将数组排序每次取最多的两个和最少的一个
* 重复上一步直到最少的为0时
* 答案还要加上第二少的食物数
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
vector<int> v;//vector 有点多此一举了,但是契合本章标题
for(int i=0;i<4;i++)//读入数据
{
int a;
scanf("%d",&a);
v.push_back(a);
}
//每次将数组从小到大排序
//每次取两个最多的和一个最少的直到最少的为0,那么第二少的就是剩下的份数
int ans=0;
sort(v.begin(),v.end());
while(v[0]--)
{
v[2]--;
v[3]--;
sort(v.begin(),v.end());
ans++;
}
cout<<ans+v[1]<<endl;
}
return 0;
}
* 问题来了:我们为什么不直接每次取最多的三份,再排序,那循环条件应该是什么呢v[1]==0
* 当然可以,但是这种解法实际上多计算了第二少食物数的个数,因此解法一为优
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
vector<int> v;
for(int i=0;i<4;i++)//读入数据
{
int a;
scanf("%d",&a);
v.push_back(a);
}
//每次将数组从小到大排序
//每次取两取三个最多的,直到第二少的食物数为0
int ans=0;
sort(v.begin(),v.end());
while(v[1]--)
{
v[2]--;
v[3]--;
sort(v.begin(),v.end());
ans++;
}
cout<<ans<<endl;
}
return 0;
}