51nod3063 小明爱正方形

3063 小明爱正方形

小明很喜欢正方形,也喜欢火柴,现在小明有一些火柴,现在小明想知道用所有的火柴棒能不能拼成一个正方形。

输入

第一行一个数T,表示数据的组数(1≤T≤10);
对于每组数据,
第一行输入一个数n,表示火柴的数目,其中1≤n≤15;
第二行n个数表示每根火柴的长度,其中火柴长度总和≤10^9。

输出

对于每组数据输出一行,
如果所有的火柴可以拼成正方形,输出true,否者输出false。

数据范围

对于25%的数据,1≤n≤8;
对于50%的数据,1≤n≤10;
对于100%的数据,1≤n≤15,1≤T≤10,每组火柴长度总和≤10^9;

输入样例

1
5
1 1 2 2 2

输出样例

true

样例解释

能拼成一个边长为2的正方形。

解析:

首先我们可以确定正方形的边长,对于最大值大于边长的或者sum%4不等于0或者火柴数目少于4的,都是false,接下来进行暴力dfs,这里是对于每一层把每根火柴忘每条边放置,判断条件是当前这条边边长小于等于sum/4,时间复杂度大约为O(4^15)。

放代码:

#include <iostream>
#include<bits/stdc++.h>
#include <algorithm>
using namespace std;
typedef long long ll;
int n;
ll a[15];
ll sum = 0;
bool used[15];
bool my_find(int x) {
    for (int i = n - 1; i >= 0; --i) {
        if (!used[i] && a[i] <= x) {
            if (a[i] == x) {
                used[i] = true;
                return true;
            }
            else {
                used[i] = true;
                bool flag = my_find(x - a[i]);
                if (flag) return true;
                used[i] = false;
            }
        }
    }
    return false;
}
int main(){
    int t;
    cin >> t;
    while (t--) {
        memset(used, false, sizeof(used));
        int cnt = 0; 
        sum = 0;
        cin >> n;
        for (int i = 0; i < n; ++i) {
            cin >> a[i];
            sum += a[i];
        }
        sort(a, a + n);
        if (sum % 4 != 0) {
            cout << "false" << endl;
            continue;
        }
        if (a[n - 1] > sum / 4) {
            cout << "false" << endl;
            continue;
        }
        bool flag = true;
        for (int i = n - 1; i >= 0; --i) {
            if (!used[i]) {
                used[i] = true;
                if (sum / 4 - a[i] == 0)continue;
                if (!my_find(sum / 4 - a[i])) {
                    flag = false;
                    break;
                }
            }
        }
        if (!flag) {
            cout << "false" << endl;
            continue;
        }
        else {
            bool f = true;
            for (int i = 0; i < n; ++i) {
                if (!used[i]) {
                    f = false;
                    break;
                }
            }
            if (f) cout << "true" << endl;
            else cout << "false" << endl;
        }
    }
    return 0;
}

上一篇:DFS的联通性问题


下一篇:【例题3】虫食算