题目描述
John计划为他的牛场建一个围栏,以限制奶牛们的活动。他有N种可以建造围栏的木料,长度分别是L1,L2…LN, 每种长度的木料无限。
修建时,他将把所有选中的木料拼接在一起,因此围栏的长度就是他使用的木料长度之和。但是聪明的John很快发现很多长度都是不能由这些木料长度相加得到的,于是决定在必要的时候把这些木料砍掉一部分 以后再使用。
不过由于John比较节约,他给自己规定:任何一根木料最多只能削短M米。当然,每根木料削去的木料 长度不需要都一样。不过由于测量工具太原始,John只能准确的削去整数米的木料,因此,如果他有两种长度分别是 7和11的木料,每根最多只能砍掉1米,那么实际上就有4种可以使用的木料长度,分别是6, 7, 10, 11。
Clevow是John的牛场中的最聪明的奶牛,John请她来设计围栏。Clevow不愿意自己和同伴在游戏时受到围栏的 限制,于是想刁难一下John,希望John的木料无论经过怎样的加工,长度之和都不可能得到她设计的围栏总长度。 不过Clevow知道,如果围栏的长度太小,John很快就能发现它是不能修建好的。因此她希望得到你的帮助,找 出无法修建的最大围栏长度。
输入格式
输入文件的第一行包含两个整数N, M (1 < N < 100, 0 < M < 3000),分别表示木料的种类和每根木料削去的最大值。
以下各行每行一个整数li (1 < li < 3000 ),表示第i根木料的原始长度。
输出格式
输出文件仅一行,包含一个整数,表示不能修建的最大围栏长度。
如果任何长度的围栏都可以修建或者这个最大值不存在,输出-1。
样例
样例输入
2 1
7
11
样例输出
15
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int length[4001234],minl,maxl,kinum;
int dis[3001];
bool used[3001];
int way[3001][3001];
const int INF=1401401003;
int gcd(int x,int y)
{
if(y==0) return x;
return gcd(y,x%y);
}
void dijkstra()
{
dis[0]=0;
used[0]=1;
int nownum=0;
for(int i=0;i<minl;i++)
{
dis[i]=way[0][i];
}
for(int i=1;i<minl;i++)
{
int minle=INF+1,minnu=-1;
for(int j=0;j<minl;j++)
{
if(used[j]) continue;
if(minle>dis[j])
{
minnu=j;
minle=dis[j];
}
}
used[minnu]=1;
for(int j=1;j<minl;j++)
{
if(j==minnu) continue;
dis[j]=min(dis[j],dis[minnu]+way[minnu][j]);
}
}
}
int main()
{
int asd=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int len;
cin>>len;
for(int j=0;j<=m;j++)
{
if(j>=len) break;
length[++kinum]=len-j;
}
}
asd=length[1];
for(int i=2;i<=kinum;i++)
{
asd=gcd(max(asd,length[i]),min(asd,length[i]));
if(asd==1) break;
}
minl=INF;
for(int i=1;i<=kinum;i++)
{
minl=min(minl,length[i]);
}
if(asd!=1||minl==1)
{
cout<<"-1\n";
return 0;
}
//Input is done.
for(int i=0;i<minl;i++)
for(int j=0;j<minl;j++)way[i][j]=INF;
for(int i=0;i<minl;i++) way[i][i]=0;
for(int i=1;i<=kinum;i++)
{
for(int j=0;j<minl;j++)
{
int pg=(j+length[i])%minl;
way[j][pg]=min(way[j][pg],length[i]);
}
}
dijkstra();
int ans=dis[1];
for(int i=1;i<minl;i++)
{
if(dis[i]>ans) ans=dis[i];
}
ans-=minl;
cout<<ans<<endl;
}