UVA 307 Sticks

回溯 +剪枝 (对剪枝要求比较高) ,一下是代码

#include <iostream>
#include <cstring>
#include <stack>
#include <algorithm>
#include <utility>
#include <functional>

using namespace std;

const int size = 200;

int get_next(int cur , int old , int *v , int *p , int num)
{
	int i = cur + 1;
	while(i < num)
	{
		if(!p[i] && v[i] != old) return i;
		++i;
	}
	return -1;
}

int main()
{
	int n;
	int v[size];
	int u[size];
	
	while(cin >> n && n)
	{
		int sum = 0;
		for(int i = 0 ; i < n ; ++i)
		{
			cin >> v[i];
			sum += v[i];
		}
		sort(v , v + n , greater<int>());
		for(int i = v[0] ; i <= sum ; ++i)
		{
			if(sum % i == 0)
			{
				memset(u , 0 , sizeof(int) * n);
				
				int m = sum / i;
				int now = v[0];
				stack<int> s;
				u[0] = 1;
				s.push(0);
				int over = 0 , cur = 0 , old = -1;
				while(m > 1 && !s.empty())
				{
					if(over)
					{
						int t = s.top(); s.pop(); u[t] = 0; old = v[t];
						if(!s.empty() && s.top() < 0) 
						{  			
							while(!s.empty() && s.top() < 0)
							{
								s.pop(); now = i; ++m; /*break;*/
								cur = s.top();
								now -= v[cur];
								s.pop(); 
								u[cur] = 0;
							}
						}
						else { cur = t; now -= v[t]; over = 0; }
						continue;
					}
					if(now == i)
					{
						--m;
						s.push(-1);
						cur = 0;
						now = 0;
					}
					if(now < i)
					{
						int r;
						do{
							r = get_next(cur ,old , v ,  u , n);
							if(r < 0 ) { over = 1; break; }
							cur = r;
							old = v[r];
						}while(now + v[r] > i);
						if(!over){
							old = -1;
							cur = r;
							now += v[r];
							s.push(r);
							u[r] = 1;
						}	
					}
				}
				
				if(m <= 1) { cout << i << endl; break; }
			}
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值