import java.util.Scanner;
import java.util.LinkedList;
import java.lang.Math;
public class Main
{
private class TV
{
public int T;
public int V;
TV( int T,int V )
{
this.T = T;
this.V = V;
}
}
private class Point
{
public int P; //物品的价格
public int L; //物品的等级
public int X; //物品代替品的个数
public int num; //物品的编号
public TV[] tvs; //物品代替品的数组
Point( int num,int P,int L,int X )
{
this.num = num;
this.P = P;
this.L = L;
this.X = X;
this.tvs = new TV[X];
}
public void setTV( int i,int T,int V )
{
this.tvs[i] = new TV( T,V );
}
}
private int N;
private int M;
private int[] d;
private Point[] ps;
Main( int M,int N )
{
this.M = M; //等级
this.N = N; //节点个数
this.d = new int[N+1];
this.ps = new Point[N+1];
}
private void Inization() //初始化数组,使它为每一个物品的价格
{
for( int i=1;i<=this.N;i++ )
{
d[i] = 0;
}
}
public int getMin( int num,int maxL,int minL ) //利用递归的方法,有点类似于深度搜索,num为节点的标号,maxL为最大等级,minL为最小等级
{
int mm = this.ps[num].P; //设置初始值
if( d[num]!=0 )
{
int al = this.ps[num].L;
if( (Math.abs(maxL-al)>M)||(Math.abs(minL-al)>M) ) //这里要判断,是不是等级是否能够参与计算
{
return -1;
}
return d[num];
}
if( this.ps[num].X==0 ) //如果没有优惠的方法的话,它的价格就是最小的
{
int al = this.ps[num].L;
d[num] = mm;
if( (Math.abs(maxL-al)>M)||(Math.abs(minL-al)>M) ) //这里要判断,是不是等级是否能够参与计算
{
return -1;
}
return mm;
}
for( int i=0;i<this.ps[num].X;i++ )
{
int t = this.ps[num].tvs[i].T; //t为节点标号
int al = this.ps[t].L;
if( (Math.abs(maxL-al)>M)||(Math.abs(minL-al)>M) ) //由于等级限制,此路到此为止
{
continue;
}
if( t<=num ) //限制环的出现
{
continue;
}
int maxL1 = this.max( maxL,al ); //找出最大的等级
int minL1 = this.min( minL,al ); //找出最小的等级
int tt = getMin( t,maxL1,minL1 );
if( tt==-1 ) //说明由于等级限制,没法进行计算,这一步只能是那个价格
tt = this.ps[t].P;
else
tt += this.ps[num].tvs[i].V; //递归解决
mm = min( mm,tt );
}
d[num] = mm;
return mm;
}
public void prM()
{
int maxL = this.ps[1].L;
int minL = this.ps[1].L;
System.out.println( this.getMin( 1,maxL,minL) );
}
public int min( int i,int j ) //获得较小者
{
if( i<j )
return i;
else
return j;
}
public int max( int i,int j ) //获得较大者
{
if( i<j )
return j;
else
return i;
}
public void setPoint( int i,int P,int L,int X )
{
this.ps[i] = new Point( i,P,L,X );
}
public void setPTV( int i,int j,int T,int V )
{
this.ps[i].setTV( j,T,V );
}
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
int M = s.nextInt();
int N = s.nextInt();
Main main = new Main( M,N );
//输入
for( int i=1;i<=N;i++ )
{
int P = s.nextInt();
int L = s.nextInt();
int X = s.nextInt();
main.setPoint( i,P,L,X );
for( int j=0;j<X;j++ )
{
int T = s.nextInt();
int V = s.nextInt();
main.setPTV( i,j,T,V );
}
}
main.prM();
}
}
这道题目,主要是参考http://blog.sina.com.cn/s/blog_69b8e8d90100yq7u.html这个大神的做法,使用的大概是dfs算法吧。
第一步是要找到终止的位置,有2种可能:
第一是在没法进行物品优惠的那个。即某个点的X==0的地方。
第二是在能某个点已经算出最小值的地方,这里就不用递归进行计算了。
注意,上面2步都要判断是不是有权限限制。
然后,每一步都独立递归计算,从下到上,不断进行递归计算,直到返回到第一个点。中间要记得权限限制和环的限制。