1 条题解

  • 0
    @ 2026-3-8 9:19:15

    目前没有人发题解,水一篇

    思路

    什么情况下一眼无解?

    所有人的能力值和模3不余零,即无法分成三个能力值和一样的组。

    如何求出答案?

    先算出平均每队能力值应为多少(即代码中sum),注意到i=1NBi1500\displaystyle\sum_{i=1}^{N} B_i \leq 1500,考虑DP。开一个三维数组:f[i][j][k]f[i][j][k],表示已分配前ii个队员,第一组能力值为jj,第二组能力值为kk,第三组用前缀和(代码中s数组)很好求出。

    转移方程?

    其实可以直接考虑第ii个人分配到第几组,转移时判断目标组是否等于原组即可。 (转移方程见代码)

    细节

    1.最后输出是需要额外判断目标答案($f[n][sum][sum])是否访问过。若无,则为无解;否则,输出答案。

    2.ff数组一定要memsetmemset为无穷大!!!,f[0][0][0]f[0][0][0]一定要初始化为0!!!别问我是怎么知道的

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=510;
    int f[N][N][N],a[N],b[N],n,s[N];
    int main()
    {
    	memset(f,0x3f,sizeof(f));
    	f[0][0][0]=0;
    	scanf("%d",&n);
    	int sum=0;
    	for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]),sum+=b[i],s[i]=s[i-1]+b[i];
    	if(sum%3){puts("-1");return 0;}
    	sum/=3;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<=sum;j++)
    			for(int k=0;k<=sum;k++)
    			{
    				if(j>=b[i])f[i][j][k]=min(f[i-1][j-b[i]][k]+(a[i]!=1),f[i][j][k]);
    				if(k>=b[i])f[i][j][k]=min(f[i-1][j][k-b[i]]+(a[i]!=2),f[i][j][k]);
    				if(s[i]-j-k>=b[i])f[i][j][k]=min(f[i-1][j][k]+(a[i]!=3),f[i][j][k]);
    			}
    	}
    	if(f[n][sum][sum]<=n)printf("%d\n",f[n][sum][sum]);
    	else puts("-1");
    	return 0;
    }
    
    • 1

    信息

    ID
    7926
    时间
    4000ms
    内存
    1024MiB
    难度
    7
    标签
    递交数
    25
    已通过
    9
    上传者