闲谈:这题首先得于处理所有可行的路线,然后路线中应当优先选取最大覆盖的路线.题目有几个细节.
1.枚举的时候应当按组合数,就是枚举了一个方案,下次起点设为它自己.
2.然后就是剩下可以枚举的层数和剩下的bus数量一定得满足剩下的bus数量<=我当前的层数所有bus数量*剩下层数.
2.然后首项一定小于公差,因为下表是从0~59.
然后剩下的就是代码实现了.
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> pi; const int N=60; int n,bus[N]; vector<pair<int,pi>>v;//第一维存覆盖bus数量,第二维存首项和公差. bool ck(int a,int d) { for(int i=a;i<60;i+=d) { if(!bus[i]) return false; } return true; } bool dfs(int dep,int u,int start,int sum) { if(u==dep) return sum==n; for(int i=start;i<v.size();i++) { auto a=v[i].first,b=v[i].second.first,c=v[i].second.second; if(sum+a*(dep-u)<n) continue; if(ck(b,c)) { for(int j=b;j<60;j+=c) bus[j]--; if(dfs(dep,u+1,i,sum+a)) return true; for(int j=b;j<60;j+=c) bus[j]++; } } return false; } int main() { cin>>n;int s; for(int i=1;i<=n;i++) {scanf("%d",&s);bus[s]++;}//把所有bus全部记录下来. //枚举合法路线. for(int i=0;i<60;i++)//枚举首项. { for(int j=i+1;j+i<60;j++)//枚举公差. { if(ck(i,j))//假如这个首项和公差合法的话. { v.push_back({(59-i)/j+1,{i,j}}); } } } sort(v.begin(),v.end(),greater<pair<int,pi>>()); int depth=1; while(!dfs(depth,0,0,0)) depth++;//最多depth次选择,我现在选了到了多少次,我上次选到哪个了,我现在已经处理了多少bus. cout<<depth<<endl; return 0; }
插一句优先队列是升序,sort是降序.