zoukankan      html  css  js  c++  java
  • 解题报告 征兵计划

     

    1.        题目 

    征兵计划(conscription.pas/c/cpp

    题目描述

    公元1940622日,德军攻占巴黎,法兰西共和国投降。希特勒为了实现其征服欧洲的野心,准备大举进攻英伦三岛。英国皇家空军紧急启动征兵计划,丘吉尔首相把这项任务交给你负责。

    司令部会告诉你每月最少所需新兵的数量。当征召或遣回一个士兵时,会有额外的支出。一旦一个士兵被征召而服役,他将得到政府每月发给的工资。司令部当然会告诉你征召一名士兵的费用,遣回一名士兵的费用和士兵每月工资。现在司令部要求,要把这个征兵计划的费用限制到最低,你每月该征召或遣回多少士兵。

    输入数据

        输入文件含有三行。第一行为月数n(不超过12)。第二行含征召一个士兵的费用,一个士兵的工资和遣回一个士兵的费用(≤100)。第三行含n个数,分别表示每月最少需要的士兵人数(≤1000)。每个数据之间有一个空格隔开。

    输出数据

        输出仅一行,表示征兵计划的最小总费用。

    样例输入

    3

    4 5 6

    10 9 11

    样例输出

      199

    2.        题目实质 

    求满足条件的最小代价。(废话)

    3.        算法

    动态规划。(但是,一共五个点,贪心过三个,搜索过四个,囧)

    因为这个题每一个月的状态都受前面的状态的影响,所以考虑动态规划。

    建立一个 f 二维数组,f[I,j] 分别表示第 I 个月有 j 个士兵时,前 I 个月总共花的最少钱数,由此可以得出动态转移方程: f[I,j]:=min(f[I-1,k]+ (j-k)*zheng || (k-j)*qian +j*gongzi).

    然后,就是这样。

    注意 k j 关系不同时的判断。

    边界条件是第一个月的人,另外,这里是正着更新。(背包是倒着更新)

    4.        注意事项

    注意状态转移时的判断。

    如何判断一个题是动态规划:当贪心不太好贪,或是可以举出反例,并且搜索复杂度太高时,写方程的话可以从状态的转移下手,感觉状态太多可以加一个变量。实在不行可以多次动态规划,或是正着跑一遍倒着跑一遍。(暴力 DP

    5.        时空复杂度  O(n^3)

    6.        程序代码

    Leve pascal

    var

     f:array[0..12,0..1000] of longint;

     i,j,k,a1,a2,a3,max,ans,n:longint;

     a:array[0..12] of longint;

    begin

     assign(input,'conscription.in');

     assign(output,'conscription.out');

     reset(input);

     rewrite(output);

     readln(n);

     readln(a1,a2,a3);

     for i:=1 to n do

     begin

      read(a[i]);

      if a[i]>max then max:=a[i];

     end;

     filldword(f,sizeof(f)>>2,maxlongint>>1);

     for i:=a[1] to max do

      f[1,i]:=i*(a1+a2);

     for i:=2 to n do

      for j:=a[i] to max do

       for k:=a[i-1] to max do

        begin

            if k>j then

             begin

              if f[i,j]>f[i-1,k]+a3*(k-j)+j*a2 then

             f[i,j]:=f[i-1,k]+a3*(k-j)+j*a2;

             end

            else

             if f[i,j]>f[i-1,k]+a1*(j-k)+j*a2 then

              f[i,j]:=f[i-1,k]+a1*(j-k)+j*a2;

           end;

        ans:=maxlongint;

           for i:=a[n] to max do

           if f[n,i]<ans then ans:=f[n,i];

      writeln(ans);

      close(input);

      close(output);

    end.

  • 相关阅读:
    NodeJS简介
    SQL学习笔记(1)
    Linux常用命令03
    Linux常用命令02
    Linux常用命令01
    Java接口和抽象类的区别
    Optional解决空指针
    JVM的内存管理机制-转载
    mysql explain详解-转载
    rabbitmq消息处理-转载
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2129359.html
Copyright © 2011-2022 走看看