洛谷打卡Day 8

题目描述
这次期末考试,kkksc03 需要考 4 科。因此要开始刷习题集,每科都有一个习题集,分别有 s1,s2,s3,s4道题目,完成每道题目需要一些时间,可能不等(A1,A2,…,​​,B1,B2,…,Bs,C1,C2,…,Cs,D1,D2,…,Ds)。

kkksc03 有一个能力,他的左右两个大脑可以同时计算 2 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。

由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。

输入格式
本题包含 5 行数据:
第 1 行,为四个正整数 s1,s2,s3,s4。

第 2 行,为 A1,A2,…,As共 s1个数,表示第一科习题集每道题目所消耗的时间。

第 3 行,为 B1,B2,…,Bs共 s2个数。

第 4 行,为 C1,C2,…,Cs共 s3个数。

第 5 行,为 D1,D2,…,Ds s4​ 个数,意思均同上。

输出格式

输出一行,为复习完毕最短时间。

输入输出样例
输入
1 2 1 3
5
4 3
6
2 4 3

输出
20
181
191
313
353
373
383

把题目拆成四个01背包问题,最后求和 每个题两种状态 左脑和右脑 耗时即是背包容量也是价值
看别的大佬的一种思想,当左右脑都为t/2时是最好的。所以当一边的大脑耗时尽量靠近t/2时,另一半的耗时就为解

题解

#include<iostream>

using namespace std;

int a[4];
int work[30];
int dp[21][1201];

int main() {
   
    for (int i = 0; i < 4; i++) cin >> a[i];
    int tot = 0;
    for (int i = 0; i < 4; i++) 
    {
        int v = 0;
        for (int j = 1; j <= a[i]; j++) cin >> work[j], v += work[j];
     
        int t1 = 0;
        for (int j = 1; j <= a[i]; j++)
            for (int k =0; k <=v/2; k++) 
            {
                
                if (k < work[j])
                   dp[j][k] = dp[j - 1][k];
                else
                    dp[j][k] = max(dp[j-1][k], dp[j - 1][k - work[j]] + work[j]);
                   t1 = max(dp[j][k], t1);
            }
        tot += max(t1, v - t1);
    }
    cout << tot << endl;
    return 0;
}

题目描述
有 n 根木棒,现在从中选 4 根,想要组成一个正三角形,问有几种选法?

答案对 109+7取模

输入格式
第一行一个整数 n。

第二行 n 个整数,第 i 个整数 ai 代表第 i根木棒的长度。

输出格式

一行一个整数代表答案。

输入输出样例
输入
4
1 1 2 2

输出
1
桶排序
https://blog.csdn.net/bqw18744018044/article/details/81738883
用到了桶,记录每个长度出现的次数,桶的编号即为木棍长度
然后遍历,去找两个相同长度的木棍(两种情况)
**二进制位移操作 >>1 等价于 /2 **
** <<1 等价于 *2 **
对x取模 = %x

题解

#include<bits/stdc++.h>

#define ll long long
#define MOD 1000000007LL
using namespace std;
ll b[5044];
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int x;
        cin>>x;
        b[x]++;
    }
    ll ans=0;
    for(int i=1;i<=5000;++i)
    {
        for(int j=i;j<=5000;++j)
        {
            if(i+j>5000)
            break;
            if(i==j)
            {
                if(b[i]>=2&&b[i<<1]>=2)
                ans=(ans+(b[i]*(b[i]-1)/2%MOD*(b[i<<1]*(b[i<<1]-1)/2)%MOD))%MOD;
            }else{
                if(b[i]>=1&&b[j]>=1&&b[i+j]>=2)
                ans=(ans+(b[i]*b[j]%MOD*(b[i+j]*(b[i+j]-1)/2)%MOD))%MOD;
            }
        }
    } 
   cout<<ans;
    return 0;
}

posted @ 2020-04-15 23:03  猫与小岛  阅读(192)  评论(0)    收藏  举报