UVA307 Sticks小木棍
生活随笔
收集整理的這篇文章主要介紹了
UVA307 Sticks小木棍
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:一開始有n根同樣的小木棍,后來將其切成長度不超過50的小木棍,問原來小木棍最短長度是多少,例如砍完后有四根,長度分別為1,2,3,4,原來長度可能為5,或10。5是最小可能長度。
分析:可以用深搜,因為它的組成長度可能性只是所有木棍長度總和的因數,所以可以直接dfs。
注意剪枝,四個剪枝:
1、當前枚舉的長木棍長度不是小木棍長的和的因數時跳過。
2、與當前小木棍長度相同的小木棍沒有使用,當前小木棍也不會使用。
3、當前是拼新的長木棍的第一個小木棍,而最后無法拼成的,直接回溯。
4、一根木棍補足長木棍剩余所需長度,而最后無法拼成的,直接回溯。
# include<iostream> # include<cstdio> # include<cmath> # include<map> # include<queue> # include<string> # include<string.h> #include<set> #include<list> # include<algorithm> using namespace std; const int maxn = 65536; int a[maxn]; int len; int maxd; int vis[maxn]; bool cmp(int u, int v) { return u > v; } bool dfs(int sum,int cur,int res,int k) {if (res==maxd) {return true;}for (int i =cur ; i < len; i++) {if (vis[i] || (i&&a[i] == a[i - 1] && !vis[i - 1]))continue;//相同長度的之前沒使用,所以這里一樣不使用if (a[i] + sum == k) {//成功拼成一個小木塊vis[i] = 1;if (dfs(0, 0, res + 1,k))return true;vis[i] = 0;return false;}if (a[i] + sum < k) {//沒拼好vis[i] = 1;if (dfs(a[i] + sum, i + 1, res,k))return true;vis[i] = 0;if (!sum)return false;//最后仍不能拼成}}return false; }int main() {while (cin >> len && len) {int sum=0;for (int i = 0; i < len; i++) {cin >> a[i];sum += a[i];}int ok = 0;sort(a, a + len,cmp);for (int i = a[0]; i <= sum/2; i++) {//從最大的開始拼if (sum % i == 0) {memset(vis, 0, sizeof(vis));maxd = sum / i;if (dfs(0, 0,0,i)) { cout << i << endl; ok = 1; break; }}}if (!ok)cout << sum << endl;}return 0; }?
總結
以上是生活随笔為你收集整理的UVA307 Sticks小木棍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高僧斗法(博弈论)
- 下一篇: UVA - 11882Biggest N