这道题很恶心,变态的dfs就不说了,而且还要剪枝。。。。开始我只想了两种剪枝,果断超时了....╮(╯▽╰)╭ 很不爽....因为对于我这种初学者把这个另类的dfs函数写出来就已经很不容易了。。。。不过这题我最终还是被我AC了哈哈~~鸟神同学来看下我的代码哈~~O(∩_∩)O!
Sticks
Time Limit:1000MS |
|
Memory Limit:10000K |
Total Submissions:86241 |
|
Accepted:19200 |
Description
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him
and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.
Output
The output should contains the smallest possible length of original sticks, one per line.
这题最后想到了6种剪枝,全用上了。。。
#include<iostream>
#include<deque>
#include<vector>
#include<algorithm>
using namespace std;
struct POS
{
int vx;
int start;
}pow;
int n,calu,ring,sum,mmax,temp;
vector<int>v;
deque<POS> vip;
int vis[65];
int mix[65];
bool next(int id)
{
if(v[id]==v[id+1])
{
if(vis[id+1]==0)
{
return true;
}
else
{
return false;
}
}
return false;
}
bool dfs(int ipry,int ix,int rest)
{
if(rest==0)
{
pow.vx=v[ipry];
while(vis[ipry]==1 && ipry>=0)
{
ipry--;
}
if(ipry<0)
{
return true;
}
else
{
vis[ipry]=1;
vip.push_front(pow);
if(dfs(ipry,ipry-1,ring-v[ipry]))
{
return true;
}
vis[ipry]=0;
vip.pop_front();
return false;
}
}
else
{
for(int i=ix;i>=0;i--)
{
if(vis[i]==1) //这货不是剪枝啊!我去。。。是谁在说这货是剪枝啊??剪枝是什么?那就是可有可无的,没有的话只是时间长一点,但是你敢说可以没这个吗?
{
continue;
}
if(!vip.empty() && v[ipry]==vip[0].vx) //剪枝2,非重要,如果这根棒棒上一根棒棒相等,则从它之后的下一个位置开始计算,该剪枝直接为0ms的目标提供了可能。
{
if(i>=vip[0].start)
{
i=vip[0].start;
continue;
}
}
if(next(i)) //剪枝3,很重要!对长度排序后,如果前面一根棒子的长度和他一样,且前面那根没用到,同理!这根也不会用到!该剪枝能对付很恶心的测试数据。
{
continue;
}
if(v[i]>rest) //重要剪枝4,如果棒棒的长度比剩余的要大,直接排除!没有这个剪枝就等着超时吧~
{
continue;
}
if(rest>mix[i]) //辅助剪枝5,该剪枝是剪枝6的辅助剪枝,其实思想还是剪枝6的思想。
{
return false;
}
temp=0;
for(int j=i;j>=0;j--)
{
if(vis[j]==1)
{
temp+=v[j];
}
}
temp=mix[i]-temp;
if(rest>temp) //重要剪枝6,这个剪枝有什么用呢??呵呵,它的唯一用处就是让你的代码时间变成0ms~~如果除了标记过的剩下的棒子的总和要大于rest,否则RF!
{
return false;
}
if(rest==ring-v[ipry])
{
pow.start=i;
}
vis[i]=1;
if(dfs(ipry,i-1,rest-v[i]))
{
return true;
}
vis[i]=0;
}
return false;
}
}
int find(int l,int r)
{
for(ring=l;ring<=r;ring++)
{
if(sum%ring!=0) //重要剪枝1,如果不能整除的话直接跳过。
{
continue;
}
memset(vis,0,sizeof(vis));
vis[n-1]=1;
vip.clear();
if(dfs(n-1,n-2,ring-v[n-1]))
{
return ring;
}
}
}
int main()
{
while(cin>>n)
{
memset(mix,0,sizeof(mix));
if(n==0)
{
break;
}
v.clear();
sum=0;
mmax=0;
for(int i=1;i<=n;i++)
{
cin>>calu;
if(calu>mmax)
{
mmax=calu;
}
sum+=calu;
v.push_back(calu);
}
sort(v.begin(),v.end());
for(int i=0;i<=v.size();i++)
{
for(int j=i;j>=0;j--)
{
mix[i]+=v[j];
}
}
find(mmax,sum);
cout<<ring<<endl;
}
return 0;
}
Memory: 224K Time: 0MS
分享到:
相关推荐
北大POJ1011-Sticks 解题报告+AC代码
详细解释 ,既有源代码又有书面文字解释,ppt,在VC6上完成
这题是道神题,神就神在,它既能让你搞懂网络流及其优化,还给了你很大的优化空间。
poj 2452 Sticks Problem.md
北京大学数据结构与算法课程作业代码,供广大学习c++的同学参考与学习
北京大学数据结构与算法课程作业代码,供广大学习c++的同学参考与学习
POJ 1006 源代码——中国剩余定理分析POJ 1006 源代码——中国剩余定理分析POJ 1006 源代码——中国剩余定理分析
北京大学数据结构与算法课程作业代码,供广大学习c++的同学参考与学习
北京大学数据结构与算法课程作业代码,供广大学习c++的同学参考与学习
poj 2488——dfs深度优先遍历 //给行数列数,求问能否遍历,给出字典序的一种遍历
北大POJ2513-Colored Sticks【TrieTree+MergeSet+EulerPath】 解题报告+AC代码
北大POJ1426-Find The Multiple【BFS+同余模】 解题报告+AC代码
POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度
晒代码之二——多重背包(POJ1276)
cpp代码-2.24.1 poj 1011
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类
北大POJ1027-The Same Game 解题报告+AC代码