uestc sticks

转自http://m.blog.csdn.net/blog/wuxinliulei/9052707

Sticks
  这一题仍然要采用深度优先搜索+剪枝 
  这一题的剪枝很重要。
  首先题意是要求木棒的最短长度,首先明确一点木棒的长度一定在最长木棒长度---所有木棒长度总和之间
  所以在读入木棒长度之后要找出最长的和长度总和两个值。
  还有一个理论上分析得出的结果   就是长木棒的灵活性较小在拼接的时候要首先拼接长木棒再考虑短木棒
  比如要拼接一个长度为8的木棒  拼接 5+3 和拼接 5+2+1 其实是等价的 但是显然前者对3的利用较好
  所以在读入数据之后对木棒的长度进行排序。从大到小。
  然后从最大木棒长度  就是数组的第一个元素开始进行枚举,
  此时又出现一个剪枝 就是长度必须是总和的约数  这个也是自然的。
  下面进行深搜
  深搜的结束条件此时也是一个剪枝 当已经组合的(木棍长度+1)* 长度之后如果等于总和则 return true 跳出循环 得出结果
  下面的判断分为三种情况  新加上的木棒长度刚好构成一个完整的木棒  还有不能构成一个完整的木棒 
  还有细分出来的起始长度为0无法构成一个完成木棒的情况 ,这是一个剪枝 如果在这种情况下都无法完成的话说明不可能在利用这个
 木棒,于是return false  这是为一个一个在for循环里的return false 不然的话都要将for循环进行到底(除非return true)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<iostream>
 6 using namespace std;
 7 #define MAX 64
 8
 9
10 int s[MAX], vis[MAX], n, len, sum;
11
12
13 bool cmp(int a, int b)
14 {
15     return a > b;
16 }
17
18 void input()
19 {
20     int i, j, temp;
21     sum = 0;
22     for (i = 0; i<n; i++)
23     {
24         scanf("%d ", &s[i]);
25         sum += s[i];
26     }
27     sort(s,s+n,cmp);
28 }
29
30
31 bool dfs(int now_len, int i, int count)
32 {
33     if ((count + 1)*len == sum)
34     {
35         return true;
36     }
37     for (int k = i; k<n; k++)
38     {
39         if (vis[k]) continue;
40         if (k&&!vis[k - 1] && s[k] == s[k - 1]) continue;
41         if (s[k] + now_len>len) continue;
42         if (now_len + s[k] == len)
43         {
44             vis[k] = 1;
45             bool result = dfs(0, 0, count + 1);
46             vis[k] = 0;
47             return result;
48         }
49         else if (now_len == 0)
50         {
51             vis[k] = 1;
52             bool result = dfs(s[k], k + 1, count);
53             vis[k] = 0;
54             return result;
55
56
57         }
58         else if (now_len + s[k]<len)
59         {
60             vis[k] = 1;
61             bool result = dfs(s[k] + now_len, k + 1, count);
62             vis[k] = 0;
63             if (result)
64                 return true;
65         }
66     }
67     return false;
68 }
69 int main()
70 {
71     //freopen("1.txt","r",stdin);
72     while (scanf("%d", &n) == 1 && n != 0)
73     {
74         input();
75         for (len = s[0]; len <= sum; len++)
76         {
77             if (sum%len) continue;
78             memset(vis, 0, sizeof(vis));
79             if (dfs(0, 0, 0))
80                 break;
81         }
82         printf("%d\n", len);
83     }
84 }
时间: 2024-09-21 10:51:22

uestc sticks的相关文章

2015 CCPC D- Pick The Sticks(UESTC 1218) (01背包变形)

http://acm.uestc.edu.cn/#/problem/show/1218 既然二维dp表示不了,就加一维表示是否在边界放置,放置一个,两个.有一个trick就是如果只放一根,那么多长都可以. wa了好多次(囧) 开始因为l[i]/2会出现小数,没注意,把所有的长度都x2就可以解决. 又wa了n次因为没注意j-l[i]时没加判断,为什么不是RE呢!不开心... /********************************************* Memory: 1140 KB

ACM学习历程—UESTC 1218 Pick The Sticks(动态规划)(2015CCPC D)

题目链接:http://acm.uestc.edu.cn/#/problem/show/1218 题目大意就是求n根木棒能不能放进一个容器里,乍一看像01背包,但是容器的两端可以溢出容器,只要两端的木棒的重心还在容器中即可. 首先由于木棒可以两端溢出.一端溢出和不溢出三种情况,所以有状态p(flag, v)表示溢出个数为flag的容量为v的情况下的最值. 于是有: p[2][j] = max(p[2][j], p[2][j-a[i]]+v[i]); p[2][j] = max(p[2][j], 

DP(01背包) UESTC 1218 Pick The Sticks (15CCPC C)

题目传送门 题意:长度为L的金条,将n根金棍尽可能放上去,要求重心在L上,使得价值最大,最多有两条可以长度折半的放上去. 分析:首先长度可能为奇数,先*2.然后除了两条特殊的金棍就是01背包,所以dp[now][j][k]表示当前状态,长度为j,使用了k条特殊金棍获得的最大价值,需要对内存和时间优化. /************************************************ * Author :Running_Time * Created Time :2015/10/2

UESTC 电子科大专题训练 数据结构 D

UESTC 1584 题意:平面坐标上有n个怪物,每个怪物有一个rank值,代表x坐标和y坐标都不大于它本身的怪物数(不包括本身) 思路:对x y坐标从小到大排序,x优先排序,用数状数组计算y坐标小于它的数量 AC代码: #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #i

uva 10003 Cutting Sticks 简单区间dp

// uva 10003 Cutting Sticks 区间dp // 经典的区间dp // dp(i,j)表示切割小木棍i-j所需要的最小花费 // 则状态转移为dp(i,j) = min{dp(i,k) + dp(k,j) + a[j]-a[i]) // 其中k>i && k<j // a[j] - a[i] 为第一刀切割的代价 // a[0] = 0,a[n+1] = L; // dp数组初始化的时候dp[i][i+1]的值为 0,这表示 // 每一段都已经是切割了的,不

hdu1455 Sticks 深搜 强剪枝

Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6035    Accepted Submission(s): 1704 Problem Description George took sticks of the same length and cut them randomly until all parts becam

UESTC 31 饭卡(Card) --背包问题

背包问题. 思路:如果m<5,此时也不能消费,所以此时答案为m m>=5: 求出背包容量为m-5,买前n-1样便宜的菜(排个序)的最大价值(即最大消费,即消费完后剩余值最接近5)最后减去最大的那个菜的价格,就得到最小的余额. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using n

UESTC 电子科大专题训练 数据结构 A

UESTC 1591 题意:求区间极值之差 思路:线段树裸题,不带更新 ACA代码: #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "ma

2017 UESTC Training for Data Structures

2017 UESTC Training for Data Structures A    水,找区间极差,RMQ怼上去. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,b,a) for (int i=b;i&