洛谷p5027 Barracuda

题意:

给定$n$个物品(三角形),对其组合称重$n+1$次,其中有一次称出的重量是错的,求最重的物品(三角形)的编号。注意,只有一种方案是合法的。

合法方案定义如下:

1、最重的物品(三角形)只有一个。

2、不存在重量不确定的物品(三角形)。

3、所有物品(三角形)的重量均为正整数。

 

思路:

首先,枚举每次称重(假设他是错的)

然后,根据题意(合法方案的定义):

1、最重的物品(三角形)只有一个。    ------->不能同时存在两个解为最大值

2、不存在重量不确定的物品(三角形)。 ------>只能有唯一解

3、所有物品(三角形)的重量均为正整数。 -------->每个解都为正整数

判断每个假设是否合法

最后,判断合法假设的数量,如果不等于$1$,就无解,否则,输出合法方案的解的最大值

 

Code:

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#include <map>
#include <set>
// #include <array>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <algorithm>
// #include <unordered_map>

using namespace std;

typedef long long ll;
typedef pair<int, int> PII;

#define Time (double)clock() / CLOCKS_PER_SEC

#define sd(a) scanf("%d", &a)
#define sdd(a, b) scanf("%d%d", &a, &b)
#define slld(a) scanf("%lld", &a)
#define slldd(a, b) scanf("%lld%lld", &a, &b)

const int N = 100 + 20;
const int M = 1e5 + 20;
const int mod = 1e9 + 7;
const double eps = 1e-6;

int n;
int b[N][N];
double a[N][N];

int gauss(){
    int c, r;
    for(c = 1, r = 1; c <= n; c ++){
        int t = r;
        for(int i = r + 1; i <= n; i ++){
            if(fabs(a[t][c]) < fabs(a[i][c])){
                t = i;
            }
        }

        if(fabs(a[t][c]) < eps) continue;

        for(int i = c; i <= n + 1; i ++) swap(a[t][i], a[r][i]);

        for(int i = n + 1; i >= c; i --) a[r][i] /= a[r][c];

        for(int i = r + 1; i <= n; i ++){
            if(fabs(a[i][c]) > eps){
                for(int j = n + 1; j >= c; j --){
                    a[i][j] -= a[i][c] * a[r][j];
                }
            }
        }
        r ++;
    }

    if(r < n + 1) return 0;

    for(int i = n; i >= 1; i --){
        for(int j = i + 1; j <= n; j ++){
            a[i][n + 1] -= a[i][j] * a[j][n + 1];
        }
    }

    for(int i = 1; i <= n; i ++){
        if(a[i][n + 1] < eps) return 0;
    }

    for(int i = 1; i <= n; i ++){
        if(a[i][n + 1] != (int)a[i][n + 1]) return 0;
    }

    int res = 0;
    for(int i = 1; i <= n; i ++){
        if(a[i][n + 1] > res) res = a[i][n + 1];
    }

    int num = 0, id = 0;
    for(int i = 1; i <= n; i ++){
        if(a[i][n + 1] == res) num ++, id = i;
    }

    if(num == 1) return id;
    else return 0;

}

void solve()
{
    sd(n);

    int k, x;
    for(int i = 1; i <= n + 1; i ++){
        sd(k);
        for(int j = 1; j <= k; j ++){
            sd(x);
            b[i][x] = 1;
        }
        sd(x);
        b[i][n + 1] = x;
    }

    int ans = 0, num = 0, res;
    for(int i = 1; i <= n + 1; i ++){
        for(int j = 1, cnt = 1; j <= n + 1; j ++){
            if(j == i) continue;
            for(int jj = 1; jj <= n + 1; jj ++){
                a[cnt][jj] = b[j][jj];
            }
            cnt ++;
        }
        ans = gauss();
        if(ans != 0) num ++, res = ans; 
    }

    if(num != 1){
        puts("illegal");
    }
    else{
        printf("%d\n", res);
    }
    
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("/home/jungu/code/in.txt", "r", stdin);
    // freopen("/home/jungu/code/out.txt", "w", stdout);
    // freopen("/home/jungu/code/out.txt","w",stdout);
#endif
    // ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T = 1;
    // sd(T);
    // init();
    // int cas = 1;
    while (T--)
    {
        // printf("Case #%d:", cas++);
        solve();
    }

    return 0;
}

 

posted @ 2020-08-09 20:06  君顾  阅读(136)  评论(0编辑  收藏  举报