当前位置: 首页 > 工具软件 > Barracuda > 使用案例 >

洛谷 P5027 Barracuda 题解

夏青青
2023-12-01

题目传送门

题目大意: n n n 个物品,称量 n + 1 n+1 n+1 次,每次选取其中若干个,但是有一次的称量得到的质量是错误的,求出最重的物品的编号。

题解

因为 n n n 只有 100 100 100,所以愉快的考虑 O ( n 4 ) O(n^4) O(n4) 做法。

显然,直接枚举哪一次称量是错误的,然后高斯消元直接搞即可。

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 110

int n;
double matrix[maxn][maxn];
double ans[maxn];
int shuru[maxn][maxn],w[maxn];
void gauss()//高斯消元 
{
	for(int i=1;i<=n;i++)
	{
		int p=i;
		for(int j=i+1;j<=n;j++)
		if(fabs(matrix[j][i])>fabs(matrix[p][i]))p=j;
		if(p!=i)swap(matrix[p],matrix[i]);
		
		for(int j=n+1;j>=i;j--)
		matrix[i][j]/=matrix[i][i];
		
		for(int j=i+1;j<=n;j++)
		for(int k=n+1;k>=i;k--)
		matrix[j][k]-=matrix[i][k]*matrix[j][i];
	}
	ans[n]=matrix[n][n+1];
	for(int i=n-1;i>=1;i--)
	{
		ans[i]=matrix[i][n+1];
		for(int j=i+1;j<=n;j++)
		ans[i]-=matrix[i][j]*ans[j];
	}
}
int anss=-1;
void check()
{
	int v=0;//如果某一行全部为0,就是无解或无数解 
	for(int i=1;i<=n;i++)
	{
		bool tf=false;
		for(int j=1;j<=n;j++)
		if(fabs(matrix[i][j])>1e-10){tf=true;break;}
		if(!tf){v=1;break;}
	}
	if(v)return;
	
	int maxans=0;//判断是否都是正整数 
	for(int i=1;i<=n;i++)
	if(fabs((int)ans[i]-ans[i])>1e-10||ans[i]<=0)return;
	for(int i=1;i<=n;i++)
	if((int)ans[i]>maxans)maxans=(int)ans[i];
	int sum=0;
	for(int i=1;i<=n;i++)
	if((int)ans[i]==maxans)sum++,v=i;
	if(sum>1)return;//判断是否只有一个最重物品
	
	if(anss!=-1)printf("illegal"),exit(0);//判断是否有多组合法方案
	anss=v;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n+1;i++)
	{
		scanf("%d",&shuru[i][0]);
		for(int j=1;j<=shuru[i][0];j++)
		scanf("%d",&shuru[i][j]);
		scanf("%d",&w[i]);
	}
	for(int i=1;i<=n+1;i++)
	{
		int tot=0;
		memset(matrix,0,sizeof(matrix));
		for(int j=1;j<=n+1;j++)
		{
			if(j==i)continue;
			tot++;
			for(int k=1;k<=shuru[j][0];k++)
			matrix[tot][shuru[j][k]]=1;
			matrix[tot][n+1]=w[j];
		}
		gauss();
		check();
	}
	if(anss==-1)printf("illegal");
	else printf("%d",anss);
}
 类似资料: