• UVA 10163


    题目链接~~>

    做题感悟:開始感觉写的非常对,可是生成数据后就发现不正确了,于是改为先求出安全度,再求最小费用。

    解题思路:

                    先 dp 解出安全度,状态转移方程: dp[ i ] [ j ]  = max( dp[ i ][ j ] ,min( dp[ i - k ][ j - 1 ]  ,g[ j ] / k ) ) , ( 0 <= k <= i  ,0 时特判)  表示枚举 j 管理几个仓库。

    这样就求出安全度。然后用背包处理一下,转化为容量为个数,价值为个人能力对安全度取余。这样计算最小的费用的时候即为:容量 * 安全度 + 相应的价值,容量大于等于 n ,这样就能够求出最小的费用了。

    代码:

    #include<iostream>
    #include<sstream>
    #include<map>
    #include<cmath>
    #include<fstream>
    #include<queue>
    #include<vector>
    #include<sstream>
    #include<cstring>
    #include<cstdio>
    #include<stack>
    #include<bitset>
    #include<ctime>
    #include<string>
    #include<iomanip>
    #include<algorithm>
    using namespace std  ;
    #define INT long long int
    const int INF = 0x3f3f3f ;
    const double esp = 0.0000000001 ;
    const double PI = acos(-1.0) ;
    const int mod = 1000000007 ;
    const int MY = 100 + 5 ;
    const int MX = 100000 + 5 ;
    int n ,m ,sum ;
    int g[MY]  ;
    int dp[MY][MY] ,p[MX] ;
    struct node
    {
        int v ,c ;
    }Tx[MY] ;
    int main()
    {
        while(scanf("%d%d" ,&n ,&m) ,n+m)
        {
            sum = 0 ;
            for(int i = 1 ;i <= m ; ++i)
            {
                cin>>g[i] ;
                sum += g[i] ;
            }
            memset(dp ,INF ,sizeof(dp)) ;
            for(int i = 1 ;i <= n ; ++i) // 先选出最低的安全度
                 dp[i][0] = 0 ;
            for(int i = 1 ;i <= n ; ++i)
              for(int j = 1 ;j <= m ; ++j)
              {
                  dp[i][j] = dp[i][j-1] ; //  当前此人无论理仓库
                  for(int k = 1 ;k <= i ; ++k) // 当前此人管理 k 个仓库
                  {
                      int Max = min(dp[i-k][j-1] ,g[j]/k) ;
                      dp[i][j] = max(dp[i][j] ,Max) ;
                  }
              }
            if(!dp[n][m])
            {
                cout<<"0 0"<<endl ;
                continue ;
            }
            int mx = dp[n][m] ;
            int C = sum/mx ,num = 0 ;
            for(int i = 1 ;i <= m ; ++i)
               if(g[i] >= mx)
               {
                   Tx[num].v = g[i]/mx ;
                   Tx[num++].c = g[i]%mx ;
               }
            memset(p ,INF ,sizeof(p)) ;
            p[0] = 0 ;
            for(int i = 0 ;i < num ; ++i)
             for(int j = C ;j >= Tx[i].v ; --j)
               p[j] = min(p[j] ,p[j-Tx[i].v] + Tx[i].c) ;
            int ans = INF ;
            for(int i = n ;i <= C ; ++i)
               ans = min(ans ,i*mx + p[i]) ;
            cout<<mx<<" "<<ans<<endl ;
        }
        return 0 ;
    }
    
    


  • 相关阅读:
    事件的基本概念
    c# 语法 字符串内插
    tcp 的编程例子
    Action 语法的简介
    wcf 的小介绍
    Socket编程
    c# base new 等关键字基础
    虚函数和继承的关系
    arraylist,list ,数组区别
    Python爬虫-selenium模拟豆瓣电影鼠标下拉
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7000725.html
Copyright © 2020-2023  润新知