awa

810816659 2020-07-28 15:16:48 2020-07-28 18:22:40

代码_{代码_{代码}^{代码}}^{代码_{代码}^{代码}}

#include<bits/stdc++.h>
using namespace std;

const int N = 66, M = 3e3+10;

M 的值不是66 M的值是总线路个数, a(59) * d(60 - a + 1) ≈ 60 * 60 / 2 ≈ 2000

struct node{
	int a, d, cover;//a首项,d公差,cover当前线路覆盖的车个数 
};

int n;
int deep = 0; 
int cnt = 0; //总线路数 
int c[N];//每一时刻的车辆数 
node k[M];//记录线路 

bool check(int a, int d){
	for(int i = a; i < 60; i += d){//遍历当前等差数列 
		if(!c[i])
			return 0;
	}
	return 1;
}

bool cmp(node a, node b){//把线路按覆盖车辆数从大到小排序 
	return a.cover > b.cover;
}

bool dfs(int depth, int bn, int x){ //分别代表剩余深度,已经上路的车,上次搜索的线路的下标 
	//
	if(!depth){
		if(bn == n)
			return 1;//找到答案返回1
		else 
			return 0;
	}
	for(int i = x/*线路可重复所以传递的x不用+1*/; i <= cnt; i++){
		int num = k[i].cover;
		int a = k[i].a;
		int d = k[i].d;
		if(num * depth + bn < n)//如果当前线路覆盖的车的数量*剩余深度(剩余路径数)+之前已经覆盖的车<总车数 
			continue;
		if(!check(a,d)) continue;//当前路线是否符合要求 
		
		for(int j = a; j < 60; j += d)//将当前线路上的覆盖的车减去 
			--c[j];
		if(dfs(depth - 1, bn + num, i))//下一层 
			return 1;//找到答案返回1
		for(int j = a; j < 60; j += d)//恢复选择前状态 
			++c[j];
	}
	return 0;
}

int main()
{
	scanf("%d", &n);
	int p;
	for(int i = 1; i <= n; i++){
		scanf("%d", &p);
		++c[p];
	}
	cnt = 0;
	
	//预处理可通线路 
	for(int a = 0; a < 60; a++){
		for(int d = a + 1; a + d < 60; d++){
			if(check(a, d))
				k[++cnt].a = a, k[cnt].d = d, k[cnt].cover = (59 - a) / d + 1;
		}
	}
	//排序  从覆盖车由多到少的路径开始搜索 
	sort(k + 1, k + 1 + cnt, cmp);//范围写错直接炸裂
	
	deep = 1;
	while(!dfs(deep, 0, 1)/*迭代加深直到搜到可行答案*/) ++deep;
	
	printf("%d", deep);
}