http://acm.pku.edu.cn/JudgeOnline/problem?id=1062
用DIJ算法,注意到等级的不同,等级差为M,那么一次设M+1个区间,使酋长都在之内,再依次独立的计算最小值,很明显可以用一个for循环;
用结构体存每一位人的物品的钱,用t[Max]存每一为的等级。
具体算法如下
#include<iostream>
#include<cmath>
using namespace std;
const int Max=100;
#define INF 10000000
struct w
{
int statu;
int m;
}s[Max];
int M;
int b[Max][Max];
int t[Max];
void DIJ(int N);
int main()
{
freopen("in.txt","r",stdin);
int N,P,L,X,i,j,xx,yy;
cin>>M>>N;
for( i=0; i<N; i++)
{
s[i].m=0;
for( j=0; j<N; j++)
b[i][j]=INF;
}
for( i=0; i<N; i++)
{
cin>>P>>L>>X;
s[i].m=P;
t[i]=L;
s[i].statu =L;
for( j=0; j<X; j++)
{
cin>>xx>>yy;
b[i][xx-1]=yy;
}
}
DIJ(N);
return 0;
}
void DIJ(int N)
{
int i,v,w,min,j,mt,k,temp[Max][Max],end(s[0].m);//end最大唯没有换的时候
int final[Max]={0};
int d[Max];
final[0]=1;
mt=t[0];//mt为酋长的等级
for(k=0; k<=M; k++)//每种范围都比较过去
{
for( i=0; i<N; i++)
for( j=0; j<N; j++)
temp[i][j]=b[i][j];
for( i=1; i<N; i++)
if(t[i]<mt-M+k||t[i]>mt+k)//不再范围内
{
for( j=0; j<N; j++)//所有和i有关的给点都删去
{
temp[i][j]=INF;
temp[j][i]=INF;
}
}
for( v=0; v<N; v++)
{
d[v]=temp[0][v];//之前些为b[0][v]给wa了n次
final[v]=0;
}
v=0;
final[v]=1;
d[v]=INF;
for( i=1; i<N; i++)
{
min=100000;
for( w=0; w<N; w++)
if( !final[w]&&d[w]<min)
{v=w;min=d[w];}
final[v]=1;
for( w=0; w<N; w++)
if(!final[w]&&(min+temp[v][w]<d[w]))
{
d[w]=min+temp[v][w];
}
}
for( i=0; i<N; i++)
for( j=0; j<N; j++)
temp[i][j]=0;
//cout<<min<<endl;
min=INF;
for( i=0; i<N; i++)
if((d[i]+s[i].m)<min&&d[i]!=INF)
{
min=d[i]+s[i].m;
j=i;
}
if(min<end)
end=min;
}
cout<<end<<endl;
}