题目描述 小D知晓的希腊单词个数为n,其中每一个单词有一个复杂度di,表示游人学习这个词语的困难程度。为了在三天中学习强度的差别尽可能地小,小D想知道,是否存在一种将词语划分成三组的方法,让游人在三天中学习词语的复杂度之和相同?
输入格式 第一行一个整数T,表示数据组数。 接下来,对于每组数据: 第一行一个整数n,表示小D知晓的希腊单词个数。 第二行中包含n个数,其中第i个非负整数di表示第i个单词的复杂度。
输出格式 对于每组数据,如果存在一种将词语划分成三组并让游人在三天中学习词语的复杂度之和相同的方法,则输出出"Yes"(不含引号);否则输出"No"(不含引号)。
样例 5 10
#include<bits/stdc++.h>
using namespace std;
int T,n,d[105],f[105][105];
bool c[105];
int cmp(int x,int y)
{
return x<y;
}
int dp(int x)
{
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
if(!c[i])
for(int j=1;j<=x;j++)
{
if(j>=d[i])
{
f[i][j]=max(f[i-1][j],f[i-1][j-d[i]]+d[i]);
if((f[i-1][j-d[i]]+d[i])>f[i-1][j])
c[i]=1;
else
c[i]=0;
}
else
{
f[i][j]=f[i-1][j];
}
}
if(f[n][x]==x)
return 1;
else
return 0;
}
int main()
{
cin>>T;
while(T--)
{
int sum=0,target=0;
memset(d,0,sizeof(d));
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>d[i];
sum+=d[i];
}
if((!sum%3)||n<=2)
{
cout<<"No"<<endl;
}
else
{
//sort(d+1,d+n+1);//转化为单调增数列
target=sum/3;
/*
问题转化为从d中取数使其值为target
那么能否找最简时一部分成立,
去除已选,然后二部分成立,end
此时target为背包容量
d[i]数值为价值与体积相等的 物品i
*/
//是否到达target
if(dp(target))
{
if(dp(target))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
else
cout<<"No"<<endl;
}
}
return 0;
}
17 19 13 22 4 20 17 4 0 4 10 1 10 19 24 23 18 8 7 4 6 10 21 8 17 12 22 21 4 8 7 0 10 15 16 20 8 6 6 16 2 14 17 10 1 9 20 20 12 9 13 17 0 19
答案 No No No Yes Yes