POJ 1062

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步都要判断是不是有权限限制。

 

然后,每一步都独立递归计算,从下到上,不断进行递归计算,直到返回到第一个点。中间要记得权限限制和环的限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值