二次联通门 : luogu P1120 小木棍 [数据加强版]
/* luogu P1120 小木棍 [数据加强版] 暴搜 + 剪枝 枚举可能的长度 挨个检查答案 二分显然正确性不能保障 搜索时从最大的开始找 放上当前木棍后的长度比枚举的长度要大, 则退出 若当前的长度与当前扫到的木棍长度相同, 或是还需要的长度与枚举的长度相同,则退出 若当前的木棍不符合要求, 则后面与它长度相同的木棍都不行 */ #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #define INF 1e7 #define Max 300 using namespace std; void read (int &now) { now = 0; char word = getchar (); while (word > '9' || word < '0') word = getchar (); while (word >= '0' && word <= '9') { now = now * 10 + word - '0'; word = getchar (); } } bool Comp (int a, int b) { return a > b; } int N; int length[Max]; int Count; int Answer; int Len; inline int max (int a, int b) { return a > b ? a : b; } int Limit, Need; int Total; bool visit[Max]; bool Dfs (int now, int Len, int number) { if (number == Total) { Answer = Need; return true; } if (Len == 0) if (Dfs (1, Need, number + 1)) return true; for (int i = now; i <= N; i++) if (!visit[i] && length[i] <= Len) { visit[i] = true; if (Dfs (i + 1, Len - length[i], number)) return true; visit[i] = false; if (Len == length[i] || Len == Need) break; while (length[i] == length[i + 1]) i++; } return false; } int main (int argc, char *argv[]) { int x, res; read (res); for (int i = 1; i <= res; i++) { read (x); if (x <= 100) { length[++N] = x; Limit += x; Need = max (x, Need); } } sort (length + 1, length + 1 + N, Comp); for (; Need <= Limit; Need++) if (Limit % Need == 0) { Total = Limit / Need; if (Dfs (1, Need, 0)) break; } printf ("%d", Answer); return 0; }