对应POJ题目:点击打开链接
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 125013 | Accepted: 29107 |
Description
Input
Output
Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
6 5
POJ 2362 的加强版
题意:给一个数n, 然后给出n个数,每个数代表一根木棍长度,求这n根木棍恰好可以组成k根长度都为len的木棍。求len的最小值。
思路:搜索枚举 + 剪枝。
1、降序排序。
2、需要组成的长度len必须为总长sum的公约数。
3、枚举区间:最大木棍长度 ~ 总木棍长度。
4、在尝试组成一根长为len的木棍时,从第一根子木棍开始,如果失败了,那这根子木棍在后面肯定也用不上,所以直接返回失败。
5、在尝试组成一根长为len的木棍时,如进行到 11 8 ... 若 8 失败了,如果后面的还是8,肯定也不会成功,那直接跳过。
6、如果需要组k根长为len的木棍,那完成k-1次匹配后应该就可以了的,最后一次应该也可以匹配。不过提交却是TLE,可能是我考虑欠妥。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define M 70
using namespace std;
int a[M];
int vis[M];
int n;
int Dfs(int cnt, int beg, int t, int key_t, int sum, int key_len)
{
if(sum == key_len){ //组成一根长为key_len的棍子
t++;
if(t == key_t) return 1; //棍子数为sum / key_len,成功。按道理这里改为 t == key_t - 1 似乎也是正确的,提交却是TLE
sum = 0;
for(beg=0; beg<n; beg++) //beg为下一根棍子的起始位置下标
if(!vis[beg]) break;
cnt = beg;
}
int i, flag = 0;
for(i=cnt; i<n; i++){
if(sum + a[i] <= key_len && !vis[i]){
vis[i] = 1;
sum += a[i];
flag = Dfs(i+1, beg, t, key_t, sum, key_len);
if(1 == flag) return 1;
sum -= a[i];
vis[i] = 0;
while(a[i] == a[i+1]) i++;
}
if(!vis[beg]) return 0;
}
return 0;
}
bool cmp(int a, int b)
{
return a > b;
}
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%d", &n), n)
{
memset(vis, 0, sizeof(vis));
int i;
int sum = 0;
for(i=0; i<n; i++){
scanf("%d", &a[i]);
sum += a[i];
}
sort(a, a+n, cmp);
int ans, key_len;
int ok = 0;
for(ans=a[0]; ans<= sum; ans++){
if(sum % ans) continue;
key_len = sum / ans;
ok = Dfs(0, 0, 0, key_len, 0, ans);
if(ok) break;
}
printf("%d\n", ans);
}
return 0;
}
原文:http://blog.csdn.net/u013351484/article/details/44538415