2018-04-26 模拟考试 答题报告

【留坑待填】...

 

  一.任务分配

Description

图书馆按顺序排列有N本书需要维护,每本书的总页数不一定相同。现有M位员工。可以给每个员工分配连续的一段书籍,让他进行维护。现在的问题是,怎么样分配,工作任务最重(需要维护的页数最多)的人维护的页数尽量少。

Input

第一行两个数,N、M。接下来N行,每行一个整数,表示一本书的页数。

Output

任务最重的人最少需要维护的页数。

Sample Input 1

5 3
3
2
4
1
5

Sample Output 1

5

Hint

对于10%的数据,N<=10

对于30%的数据,N<=10^4

对于100%的数据,N<=10^5,M<=N。

一本书的页数最多10^4。

 

老师说这次全是dp, 我还真的信了555...;

 

这tm显然是二分啊, 做过了三次了不说了;

代码 :

//By zZhBr
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define int long long

int n, m;

int a[100010];

int sum, lss;

bool check(int x)
{
    int non = 0;
    int lst = 0;
    for(register int i = 1 ; i <= n ; i ++)
    {
        lst += a[i];
        if(lst > x)
        {
            non++;
        //    printf("mid == %d, lst == %d, non == %d\n",x, lst, non);
            lst = 0;
            i = i - 1;
        //    continue;
        }     
    }
    if(lst != 0) non++;
    //printf("mid == %d, non == %d\n", x, non);
    if(non > m) return 1;
    else return 0;
    
}

signed main()
{
    cin >> n >> m;
    
    for(register int i = 1 ; i <= n ; i ++) 
    {
        scanf("%lld", &a[i]);
        sum += a[i];
        lss = max(lss, a[i]);
    }
    
    if(m >= n)
    {
        int ans = 0;
        for(register int i = 1 ; i <= n ; i ++)
        {
            ans = max(ans, a[i]);
        }
        cout << ans << endl;
        return 0;
    }
    
    int l = lss, r = sum , mid;

    while(l < r)
    {
        int mid = l + r >> 1;
    //    cout << mid << endl;
        bool f = check(mid);
        if(f)
        {
            l = mid + 1;
        }
        else
        {
            r = mid;
        }
    }
    
    cout << l << endl;
    return 0;
    
    
    
}
zZhBr

水!

 

 

二.吃夜宵

Description

众所周知,pb是个长相好,身材好,人品好的三好少年,他每个月都要拿出很多的零花钱来孝敬父母、孝敬老师等等。所以这个月他的荷包终于顶不住了!这天晚上,当他和室友去吃夜宵时,看到那么多喷香的夜宵,他恨不得每样都吃一遍,但是他的经济情况已经不允许了。但是第二天就是发工资的日子,所以他决定今朝有酒今朝醉,把所有的钱都花掉! 一共有n样夜宵,每样都有一个价格Vi,pb每样夜宵最多买一样!他一共有C元钱,因为他想尽量多吃点夜宵,所以当他买完夜宵后,剩余的钱一定不够再买任何一样其他的夜宵了。他想知道一共有多少种买法,好来看看哪种买法最合算。

Input

第一行一个数T,表示一共T组数据。每组数据第一行两个数N,C。接下来一行N 个数,表示N种夜宵的价格。

Output

输出T行,每行第一个数为数据编号,然后是买法总数。

Sample Input 1

1
6 25
8 9 8 7 16 5

Sample Output 1

1 15

Hint

对10%的数据,N<=10, C<=200

对20%的数据,C<=1000

T<=10 , N <= 30 , C <= 10000

 

这题明显背包!

然而我没做出来。

可以看这个代码666: %%%YoungNeal 

这个坑填不了;

 

算了留下我的辣鸡10分代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <bitset>
using namespace std;
#define LL long long

int T, n, m;

int a[35];


int main()
{
    cin >> T;
    for(register int time = 1 ; time <= T ; time ++)
    {
        scanf("%d%d", &n, &m);
        
        for(register int i = 1 ; i <= n ; i ++)
        {
            scanf("%d", &a[i]);
        }
        
        sort(a + 1, a + 1 + n);
        
        //    LL f[(1<<n)+1];
        //    memset(f, 0, sizeof f);
            
            LL e = 1 << n;
            LL cnt = 0;
            for(register LL i = 0 ; i <= e ; i ++)
            {
                LL my = 0;
                bool flag = 0;
                
                for(register int j = 1 ; j <= n ; j ++)
                {
                    if(i & (1 << (j - 1)))
                    {
                        my += a[j];
                    }
                    if(my > m) 
                    {
                        goto End;
                    }
                }

                
                
                    for(register int j = 1 ; j <= n ; j ++)
                    {
                        if(i & (1 << (j - 1))) continue;
                        if(my + a[j] <= m) goto End;
                        else if(my + a[j] > m) break;
                    }
                
                cnt++;
            //    printf("status : %d, money : %d, cnt : %d\n", i, my, cnt);
                End:;
                
            }
            
            printf("%d %lld\n", time, cnt);
            continue;
        
        
        
    }
    return 0;
}
zZhBr

 

 经过一下午的挣扎加上te神犇的指导, 终于A了这道题;

下面说说思路;

先进行一波排序;

设dp[i] [j], 表示对于第i个数, 0 ~ i的数必须选, i+1这个数必须不选, i+2~n的数可选可不选;

我们为什么要这么设? 因为我们发现,要保证最后的结果不能买任何东西, 我们就要知道我们所没有选的最廉价的物品是什么;

因为我们从小到大排了序, 就保证了i+1是我们所没有选择的最小的数;(机智)!

这样定义的话, 我们就把这个问题分成了n+1个阶段, 每个阶段互不干扰, 便于最后求和, 棒棒的!

我们首先先求出排序后序列的前缀和, 然后进行第一波转移(其实是初始化) : dp[i] [m-sum[i]] = 1;(m - sum[i] >= 0);

如果a[1] > m 直接退出byby。

然后从0开始枚举i;为什么从0开始枚举? 因为保证枚举到所有的状态, 当i == 0的时候的状态也是独立的一个状态;

第二维枚举j : i + 2 ->n, 为什么要从i+2开始?因为我们保证了i+1不选, 而我们要从i+2到n中选择所有可以选择的数进行转移;

第三维枚举p值, 从0到m - a[i], 为什么不是从m-a[i]到0? 因为, 我们要保证每一个数只选择一次,如果从后往前转移的话, 我们就不能保证这个数只选择了一次;

枚举所有可能的情况求和;ok。

代码奉上:

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define int long long

int T, n, m;
int a[10010];
int dp[35][10010];
int sum[10010];

signed main()
{
    cin >> T;
    for(register int time = 1 ; time <= T ; time ++)
    {
        memset(dp, 0, sizeof dp);
        memset(sum, 0, sizeof sum);
        scanf("%lld%lld", &n, &m);
        
        for(register int i = 1 ; i <= n ; i ++) 
        {
            scanf("%lld", &a[i]);
        }
        
        sort(a + 1, a + 1 + n);
        
        if(a[1] > m)
        {
            printf("%d 0\n", time);
            continue;
        }
        
    //    a[n+1] = m;
        
        for(register int i = 1 ; i <= n ; i ++)
        {
            sum[i] = sum[i-1] + a[i];
        }
        
        dp[0][m] = 1;
        
        for(register int i = 0 ; i <= n ; i ++)
        {
            if(m - sum[i] >= 0)
            {
                dp[i][m-sum[i]] = 1;
                //printf("dp[0][%d] == %d \n ",m-sum[i],dp[0][m-sum[i]]);
            } 
            
        }
        
        for(register int i = 0 ; i <= n ; i ++) 
        {
            for(register int j = i + 2 ; j <= n ; j ++)
            {
                for(register int p = 0 ; p + a[j] <= m ; p ++)
                {
                    dp[i][p] += dp[i][p+a[j]]; 
                //    if(dp[i][p]!=0)printf("dp[%d][%d]=%d\n",i,p,dp[i][p]);
                }
                //cout << endl;
            }
        }
        
        
        
        int ans = 0;
        
        for(register int i = 0 ; i <= n ; i ++)
        {
            for(register int j = 0 ; j < a[i+1] ; j ++)
            {
                ans += dp[i][j];
            }
        }
        
        printf("%lld %lld\n", time , ans);
    }
    return 0;
}
zZhBr

 

 

 

 

三.货车运输

 

(待添加)...

转载于:https://www.cnblogs.com/BriMon/p/8952030.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
开发微信小程序考试答题卡的功能包括用户授权认证、身份信息登记登录、身份信息查看、在线考试、管理员模拟考试列表、考试状态数据列表检索、选择要参加的考试类型、对多种类型的题目进行作答、查看已完成评分的考题、答题卡记录、微信服务通知等。\[1\]此外,还可以添加练习功能,包括顺序练习、随机练习、专项练习、题型练习等,以及答题模式和背题模式,实时查看答题卡,统计答题情况,记忆功能等。\[2\]开发者可以参考船长在船上的博客中关于前端开发的经验和技术分享,以获取更多关于开发微信小程序考试答题卡的相关信息。\[3\] #### 引用[.reference_title] - *1* *3* [微信小程序在线考试项目开发-注册登录功能](https://blog.csdn.net/SmartJunTao/article/details/126809683)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [微信小程序,基于考研考试等定做的小程序,有前后端完整源码和数据库,已开发上手](https://blog.csdn.net/weixin_51812604/article/details/127250424)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值