利用动态规划算法来进行买卖双方定价调整

package dp;


import java.math.BigDecimal;
import java.util.Vector;


public class dpTest {  
 
//根据总重量m,计算哪些可以被选中。选中的项,其select属性为1
//根据总重量,求最大值
    public void  backpack(int m,Vector<Item> itemList){  
    //初始化数据
    int n=itemList.size();//总数
    int w[]=new int[n];//重量
    int p[]=new int[n];//值
    for(int i=0;i<n;i++)
    {
    Item item=itemList.get(i);
    w[i]=item.amount;
    p[i]=item.repay;
    }
   
        //c[i][v]表示前i件物品恰放入一个重量为m的背包可以获得的最大价值  
        int c[][]= new int[n+1][m+1];  
        for(int i = 0;i<n+1;i++)  
            c[i][0]=0;  
        for(int j = 0;j<m+1;j++)  
            c[0][j]=0;  
        //  
        for(int i = 1;i<n+1;i++){  
            for(int j = 1;j<m+1;j++){  
                //当物品为i件重量为j时,如果第i件的重量(w[i-1])小于重量j时,c[i][j]为下列两种情况之一:  
                //(1)物品i不放入背包中,所以c[i][j]为c[i-1][j]的值  
                //(2)物品i放入背包中,则背包剩余重量为j-w[i-1],所以c[i][j]为c[i-1][j-w[i-1]]的值加上当前物品i的价值  
                if(w[i-1]<=j){  
                    if(c[i-1][j]<(c[i-1][j-w[i-1]]+p[i-1]))  
                        c[i][j] = c[i-1][j-w[i-1]]+p[i-1];  
                    else  
                        c[i][j] = c[i-1][j];  
                }else  
                    c[i][j] = c[i-1][j] ;  
            }  
        } 
      //计算哪些可以被选中  
      //从最后一个状态记录c[n][m]开始逆推  
      for(int i = n;i>0;i--){  
          //如果c[i][m]大于c[i-1][m],说明c[i][m]这个最优值中包含了w[i-1](注意这里是i-1,因为c数组长度是n+1)  
          if(c[i][m]>c[i-1][m]){  
         Item item=itemList.get(i-1);
         item.select =1;//为1的是被选择的 
              m-=w[i-1];  
          }  
      }  
    }  
//根据总重量m,计算哪些可以被选中。选中的项,其select属性为1
    //根据总重量,求最小值
    public void  backpackmin(int m,Vector<Item> itemList){  
    //初始化数据
    int n=itemList.size();//总数
    int w[]=new int[n];//重量
    int p[]=new int[n];//值
    for(int i=0;i<n;i++)
    {
    Item item=itemList.get(i);
    w[i]=item.amount;
    p[i]=item.repay;
    }
   
        //c[i][v]表示前i件物品恰放入一个重量为m的背包可以获得的最大价值  
        int c[][]= new int[n+1][m+1];  
        for(int i = 0;i<n+1;i++)  
            c[i][0]=999999999;  
        for(int j = 0;j<m+1;j++)  
            c[0][j]=999999999;  
        //  
        for(int i = 1;i<n+1;i++){  
            for(int j = 1;j<m+1;j++){  
                //当物品为i件重量为j时,如果第i件的重量(w[i-1])小于重量j时,c[i][j]为下列两种情况之一:  
                //(1)物品i不放入背包中,所以c[i][j]为c[i-1][j]的值  
                //(2)物品i放入背包中,则背包剩余重量为j-w[i-1],所以c[i][j]为c[i-1][j-w[i-1]]的值加上当前物品i的价值  
                if(j<=w[i-1]){
                //如果当前重量小于第i件物品时,比较当前物品和上一次的c[][]的值,取最小的
                if (p[i-1]>c[i-1][j])
                c[i][j]=c[i-1][j];
                else
                c[i][j]=p[i-1];
                }
                else {  //如果当前重量大于第i件物品时,
                    //(1)物品i不放入背包中,所以c[i][j]为c[i-1][j]的值  
                    //(2)物品i放入背包中,则背包剩余重量为j-w[i-1],所以c[i][j]为c[i-1][j-w[i-1]]的值加上当前物品i的价值  
                    if(c[i-1][j]>(c[i-1][j-w[i-1]]+p[i-1]))  
                        c[i][j] = c[i-1][j-w[i-1]]+p[i-1];  
                    else  
                        c[i][j] = c[i-1][j];            
                 
                }
               
               
              
            }  
        }  
     //计算哪些可以被选中  
      //从最后一个状态记录c[n][m]开始逆推  
      for(int i = n;i>0;i--){  
          //如果c[i][m]小于c[i-1][m],说明c[i][m]这个最优值中包含了w[i-1](注意这里是i-1,因为c数组长度是n+1)  
          //m>-1
     if (m>0)
     {  
       if(c[i][m]<c[i-1][m]){  
         Item item=itemList.get(i-1);
         item.select =1;//为1的是被选择的 
              m-=w[i-1];  
          }
     }
      }  
    }    



    public int [][] pack(int m,int n,int w[],int p[]){  
        //c[i][v]表示前i件物品恰放入一个重量为m的背包可以获得的最大价值  
        int c[][]= new int[n+1][m+1];  
        for(int i = 0;i<n+1;i++)  
            c[i][0]=0;  
        for(int j = 0;j<m+1;j++)  
            c[0][j]=0;  
        //  
        for(int i = 1;i<n+1;i++){  
            for(int j = 1;j<m+1;j++){  
                //当物品为i件重量为j时,如果第i件的重量(w[i-1])小于重量j时,c[i][j]为下列两种情况之一:  
                //(1)物品i不放入背包中,所以c[i][j]为c[i-1][j]的值  
                //(2)物品i放入背包中,则背包剩余重量为j-w[i-1],所以c[i][j]为c[i-1][j-w[i-1]]的值加上当前物品i的价值  
                if(w[i-1]<=j){  
                    if(c[i-1][j]<(c[i-1][j-w[i-1]]+p[i-1]))  
                        c[i][j] = c[i-1][j-w[i-1]]+p[i-1];  
                    else  
                        c[i][j] = c[i-1][j];  
                }else  
                    c[i][j] = c[i-1][j] ;  
            }  
        }  
        return c;  
    }  
    
    public int [][] packmin(int m,int n,int w[],int p[]){  
        //c[i][v]表示前i件物品恰放入一个重量为m的背包可以获得的最大价值  
        int c[][]= new int[n+1][m+1];  
        for(int i = 0;i<n+1;i++)  
            c[i][0]=99999999;  
        for(int j = 0;j<m+1;j++)  
            c[0][j]=99999999;  
        //  
        for(int i = 1;i<n+1;i++){  
            for(int j = 1;j<m+1;j++){  
                //当物品为i件重量为j时,如果第i件的重量(w[i-1])小于重量j时,c[i][j]为下列两种情况之一:  
                //(1)物品i不放入背包中,所以c[i][j]为c[i-1][j]的值  
                //(2)物品i放入背包中,则背包剩余重量为j-w[i-1],所以c[i][j]为c[i-1][j-w[i-1]]的值加上当前物品i的价值  
                if(j<=w[i-1]){
                //如果当前重量小于第i件物品时,比较当前物品和上一次的c[][]的值,取最小的
                if (p[i-1]>c[i-1][j])
                c[i][j]=c[i-1][j];
                else
                c[i][j]=p[i-1];
                }
                else {  //如果当前重量大于第i件物品时,
                    //(1)物品i不放入背包中,所以c[i][j]为c[i-1][j]的值  
                    //(2)物品i放入背包中,则背包剩余重量为j-w[i-1],所以c[i][j]为c[i-1][j-w[i-1]]的值加上当前物品i的价值  
                    if(c[i-1][j]>(c[i-1][j-w[i-1]]+p[i-1]))  
                        c[i][j] = c[i-1][j-w[i-1]]+p[i-1];  
                    else  
                        c[i][j] = c[i-1][j];            
                 
                }
               
               
              
            }  
        }  
        return c;  
    }  
 
    /**  
     * 逆推法求出最优解  
     * @param c  
     * @param w  
     * @param m  
     * @param n  
     * @return  
     */  
    public int[] printPackmin(int c[][],int w[],int m,int n){  
          
        int x[] = new int[n];  
        //从最后一个状态记录c[n][m]开始逆推  
        for(int i = n;i>0;i--){  
            //如果c[i][m]小于c[i-1][m],说明c[i][m]这个最优值中包含了w[i-1](注意这里是i-1,因为c数组长度是n+1)  
           //m必须大于0
        if (m>-1)
        {
         if(c[i][m]<c[i-1][m]){  
                x[i-1] = 1;  
                m-=w[i-1];  
              }
        }
        }  
        for(int j = 0;j<n;j++)  
            System.out.println(x[j]);  
        return x;  
    }     
  
    
    /**  
     * 逆推法求出最优解  
     * @param c  
     * @param w  
     * @param m  
     * @param n  
     * @return  
     */  
    public int[] printPack(int c[][],int w[],int m,int n){  
          
        int x[] = new int[n];  
        //从最后一个状态记录c[n][m]开始逆推  
        for(int i = n;i>0;i--){  
            //如果c[i][m]大于c[i-1][m],说明c[i][m]这个最优值中包含了w[i-1](注意这里是i-1,因为c数组长度是n+1)  
            if(c[i][m]>c[i-1][m]){  
                x[i-1] = 1;  
                m-=w[i-1];  
            }  
        }  
        for(int j = 0;j<n;j++)  
            System.out.println(x[j]);  
        return x;  
    }  
    public int sumSelect(int x[],int p[]){  
    int sum=0;
    for (int i=0;i<x.length;i++)
         {
          if (x[i]==1)
          {
          sum+=p[i];
          }
         } 


        return sum;  
    }
    //计算调整后的比例
    public double[] calc(int sum,int profit,int[] p)
    {
    double d1=sum-profit;
    d1=d1/2;
    d1=sum-d1;
    double d=d1/sum;//计算收益和 需求的差值,并平均
    //对进行调整后。
    double pd[]=new double[p.length];
    for (int i=0;i<pd.length;i++)
         {
            double f = p[i]*d;
            BigDecimal b = new BigDecimal(f);
            pd[i] = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//保留两位小数
            System.out.print(p[i]+" ");  
            
            System.out.println(pd[i]);  
         }    
    return pd;
    }
    
    //计算调整后的比例,返回结果为-1,无满足条件,大于0,则为实际值
    public double makePrice(int profit,Vector<Item> itemList)
    {
    //先计算总值
    int sum=0;
        for (int i=0;i<itemList.size();i++)
        {
        Item item=itemList.get(i);
        if (item.select==1)  sum=sum+item.repay ;
        }  
        //如果实际大于等于预期,则选择有效
        if (sum>=profit)
        {
     double d1=sum-profit;
     d1=d1/2;
     d1=sum-d1;
     double d=d1/sum;//计算预期和实际的差值,并平均
     //对预期进行调整。
     double realIncome=0.0;
          for (int i=0;i<itemList.size();i++)
          {
        Item item=itemList.get(i);
        if (item.select==1)
        {
        double f = item.repay*d;
                 BigDecimal b = new BigDecimal(f);
                 item.profit = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//保留两位小数
                 realIncome=realIncome+item.profit ;
        }
          }
          BigDecimal b1 = new BigDecimal(realIncome);
          realIncome = b1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//保留两位小数
         //返回实际值
          return realIncome;
        }
        else return -1;
   


    }
       
    //计算调整后的比例,返回结果为-1,无满足条件,大于0,则为实际值
    //该函数用于 应付账单额度大,而买方(出资方)金额少,希望出资方的收益小于贴现额。
    //profit为贴现额,sum为卖方收益,应该sum<profit
    public double makePricemin(int profit,Vector<Item> itemList)
    {
    //先计算总值
    int sum=0;
        for (int i=0;i<itemList.size();i++)
        {
        Item item=itemList.get(i);
        if (item.select==1)  sum=sum+item.repay ;
        }  
        //如果收益小于贴现,则选择有效
        if (sum<profit)
        {
     double d1=profit-sum;
     d1=d1/2;
     d1=sum+d1;
     double d=d1/sum;//计算预期和实际的差值,并平均
     //对预期进行调整。
     double realIncome=0.0;
          for (int i=0;i<itemList.size();i++)
          {
        Item item=itemList.get(i);
        if (item.select==1)
        {
        double f = item.repay*d;
                 BigDecimal b = new BigDecimal(f);
                 item.profit = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//保留两位小数
                 realIncome=realIncome+item.profit ;
        }
          }
          //返回实际值
          BigDecimal b1 = new BigDecimal(realIncome);
          realIncome = b1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//保留两位小数
          return realIncome;
        }
        else return -1;
   


    }
   
    
    public static void main(String args[]){  
   
    Vector<Item> itemList=new Vector<Item>();


    Item sellItem=new Item();
    sellItem.id="1";
    sellItem.amount =20;
    sellItem.repay =7;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="2";
    sellItem.amount =10;
    sellItem.repay =3;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="3";
    sellItem.amount =15;
    sellItem.repay =4;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="4";
    sellItem.amount =16;
    sellItem.repay =5;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="5";
    sellItem.amount =17;
    sellItem.repay =5;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="6";
    sellItem.amount =25;
    sellItem.repay =6;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="7";
    sellItem.amount =22;
    sellItem.repay =6;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="8";
    sellItem.amount =21;
    sellItem.repay =7;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="9";
    sellItem.amount =20;
    sellItem.repay =8;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="10";
    sellItem.amount =30;
    sellItem.repay =8;
      itemList.add(sellItem);
  
     
    int m = 100;  //总重量
    int repay=30;//预期贴现
        
        dpTest pack = new dpTest();  
        pack.backpackmin(m, itemList);  
        double infact=pack.makePricemin(repay, itemList);
        if (infact>0)
        {
          System.out.println("卖方预期贴现:"+repay+" ,实际贴现:"+infact);
          for (int i=0;i<itemList.size();i++)
          {
        Item item=itemList.get(i);
        if (item.select==1)  
        System.out.println(item.id+":买方预期收益: "+item.repay+" 实际收益:"+item.profit);
       
          }
        }
        else System.out.println("无匹配项! ");
      /*   
    Vector<Item> itemList=new Vector<Item>();


    Item sellItem=new Item();
    sellItem.id="1";
    sellItem.amount =1000;
    sellItem.repay =32;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="2";
    sellItem.amount =1000;
    sellItem.repay =29;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="3";
    sellItem.amount =1000;
    sellItem.repay =33;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="4";
    sellItem.amount =2000;
    sellItem.repay =56;
      itemList.add(sellItem);
      sellItem=new Item();
    sellItem.id="5";
    sellItem.amount =2000;
    sellItem.repay =60;
      itemList.add(sellItem);
      int m = 5000;  //总量
      int repay=150;//预期收益
        
        dpTest pack = new dpTest();  
        pack.backpackmin(m, itemList);  
        double infact=pack.makePricemin(repay, itemList);
        if (infact>0)
        {
          System.out.println("卖方预期贴现:"+repay+" ,实际贴现:"+infact);
          for (int i=0;i<itemList.size();i++)
          {
        Item item=itemList.get(i);
        if (item.select==1)  
        System.out.println(item.id+":买方预期收益: "+item.repay+" 实际收益:"+item.profit);
       
          }
        }
        else System.out.println("无匹配项! ");
    */
   
    /*
   
    int m = 100;  //总重量
        int n = 10; //数量, 
        int w[]={20,10,15,16,17,25,22,21,20,30}; //单个重量 
        int p[]={7,3,4,5,5,6,6,7,8,8};  //值
        dpTest pack = new dpTest();  
        int c[][] = pack.pack(m, n, w, p);  
        int s[]= pack.printPack(c, w, m,n); 
        int sumselect=pack.sumSelect(s, p);
        System.out.println(sumselect); 
        pack.calc(sumselect, 30, p);
      */
         
        
   
      /* //求最小值
    int m = 30;  //总重量
        int n = 9; //数量, 
        int w[]={2,5,3,6,4,8,7,9,9}; //单个重量 
        int p[]={8,15,15,14,15,10,30,10,9};  //值
        dpTest pack = new dpTest();  
        int c[][] = pack.packmin(m, n, w, p);  
        pack.printPackmin(c, w, m,n); 
        
      int m = 30;  //总重量
        int n = 10; //数量, 
        //int w[]={3,4,5,6,7,8,9,10,11,12}; //单个重量 
        //int p[]={4,5,6,9,8,7,6,5,4,3};  //值
        int w[]={3,4,5,6,7,8,9,10,11,12}; //单个重量 
        int p[]={4,5,6,9,8,7,6,5,4,3};  //值
        dpTest pack = new dpTest();  
        int c[][] = pack.packmin(m, n, w, p);  
        pack.printPackmin(c, w, m,n); 
    */
    }  

}  



/*******item类

package dp;


public class Item {
  public  String id;
  public int amount;//额度
  public int repay; //预期贴现
  public double profit;//实际贴现
  public int select;//是否选择标识
  
  public Item()
  {
id="";
amount=0;
select=0;
repay=0;
profit=0.0;
  }
  public Item(String id,int amount,int repay)
  {
 this.id=id;
 this.amount =amount;
 this.repay=repay;
  }
 
   
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值