• yp训练赛3/21


    A题-饭卡

    B题-Balance

    C题-已补(完全背包)

    D题-已补(完全背包)

    E题-Treasure Hunt II

    F题-待补

    G题-待补

    H题-Relocation

    I题-Buy the souvenirs

    J题-待补

     

    A题-饭卡 

    返回列表

    题意:

    即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)

    有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。

    思路:

    卡上余额先减5块,价格排序,去掉最大值,然后01背包,这里有一个坑点,余额事先小于5块,直接输出余额,不用再去算了

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    const int maxn=1e4+10;
    int t,n,a[maxn],m;
    int dp[maxn];
    int main() {
        while(~scanf("%d",&n)){
            if(n==0){break;}
            for(it i=0;i<n;i++){
                scanf("%d",&a[i]);
            }
            scanf("%d",&m);
            sort(a,a+n);
            mem(dp,0);
            dp[0]=1;
            int mm=m-5;
            if(mm<0){printf("%d
    ",m);continue;}
            for(it j=0;j<n-1;j++){
                for(it i=mm;i>=1;i--){
                    if(i-a[j]>=0 && dp[i-a[j]]){
                        dp[i]=dp[i-a[j]];
                    }
                }
            }
            int sum=0;
            for(it i=mm;i>=0;i--){
                if(dp[i]){sum=i;break;}
            }//cout<<sum<<endl;
            printf("%d
    ",m-sum-a[n-1]);
        }
        return 0;
    }

    B题-Balance

    返回列表

    好像是hdu题目,做过的

    题意:

    就是给你n个勾子位置,m个砝码,问有多少平衡的情况

    思路:

    因为左边是负数,所以把20*15*25==7500扩大一倍0~7499代表左边,7501~15000代表右边,差不多背包套一下就过了

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    const int maxn=1e4+10;
    int n,m,c[25],g[25];
    int dp[25][15010];
    int main() {
        while(~scanf("%d%d",&n,&m)){
          for(it i=0;i<n;i++){
            scanf("%d",&c[i]);
          }
          for(it i=1;i<=m;i++){
            scanf("%d",&g[i]);
          }
          mem(dp,0);dp[0][7500]=1;
          for(it i=1;i<=m;i++){
            for(it j=0;j<=15000;j++){
                if(dp[i-1][j]){
                    for(it k=0;k<n;k++){
                        if(j+g[i]*c[k]>=0 && j+g[i]*c[k]<=15000){
                            dp[i][j+g[i]*c[k]]+=dp[i-1][j];
                        }
                    }
                }
            }
          }
          printf("%d
    ",dp[m][7500]);
        }
        return 0;
    }

    E题-Treasure Hunt II

    返回列表

    题意:

    有两个人,有n个城堡,城堡每个都有黄金w,城堡两两连接,距离都是1

    两个人的距离不能超过m,他们有 t 天可以探索城堡得到黄金,问他们最多能得到多少黄金

    题目给了两人的初始点(两个人刚开始在一起),在初始点不需要花费时间就可以得到这座城堡的黄金。

    思路:

    肯定是从初始点左右先扩大长度,然后再判断往左还是往右得到的黄金多。模拟即可边界不能超过……

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    const int maxn=1e5+10;
    int t,n,pos,m;
    ll a[maxn];
    int main() {
        while(~scanf("%d%d",&n,&pos)){a[0]=0;
            for(it i=1;i<=n;i++){scanf("%lld",&a[i]);a[i]+=a[i-1];}
            scanf("%d%d",&m,&t);
            ll ans=0;
            for(it i=max(1,pos-t);i<=pos;i++){
                int pos2=min(i+m,pos+t);pos2=min(pos2,n);
                ll sum=a[pos2]-a[i-1];//cout<<pos2<<sum<<endl;
                int pos3=t-max(pos-i,pos2-pos);
                ll sum1=sum+a[i-1]-a[max(i-pos3-1,0)];
                ll sum2=sum+a[min(n,pos2+pos3)]-a[pos2];
                ans=max(ans,max(sum1,sum2));//cout<<ans<<sum1<<sum2<<endl;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }

    H题-Relocation

    返回列表

    题意:

    有n件物品(n<=10),有两辆车分别可以载不大于c1或者c2大小的物品,物品大小不会超过c1或者c2的。

    两辆车同时出发回来,算一趟,问最少几趟可以运完

    思路:

    因为n<=10,可以暴力枚举出所有一趟运输的可能性fangan[],这些可能性用状态压缩保存,这里有一个状态转移方程

    dp[ j | fangan[i] ]=min(dp[j]+1,dp[j | fangan[i]] );这个方程要满足j 和 fangan[i]没有交集,就是没有重复送同一件物品

    可以得到dp[(1<<n)-1]就是最少的运输方案

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    const int maxn=(1<<10)+10;
    int t,n,m,c1,c2;
    int dp[maxn],vis[15],a[15],fan[maxn];
    bool cmp(int a,int b){return a>b;}
    bool check(int zhi){
        int sum=0,ge=0;
        for(it i=0;i<n;i++){
            if(zhi&(1<<i)){sum+=a[i];vis[ge++]=a[i];}
        }
        if(sum>c1+c2){return 0;}
        int zhh=1<<ge;
        for(it i=1;i<zhh;i++){
            int ans=0;
            for(it j=0;j<ge;j++){
                if(i&(1<<j)){ans+=vis[j];}
            }
            //cout<<ans<<" "<<sum-ans<<endl;
            if(ans<=c1 && sum-ans<=c2){return 1;}
            if(ans<=c2 && sum-ans<=c1){return 1;}
        }
        return 0;
    }
    int main(){
        scanf("%d",&t);int c=1;
        while(t--){
            scanf("%d%d%d",&n,&c1,&c2);
            for(it i=0;i<n;i++){scanf("%d",&a[i]);}
            int zhi=1<<n,ge=0;
            for(it i=1;i<zhi;i++){//cout<<i<<" :"<<endl;
                if(check(i)){
                    fan[ge++]=i;
                }
            }
            mem(dp,inf);dp[0]=0;
            for(it i=0;i<ge;i++){
                for(it j=zhi-1;j>=0;j--){
                    if((j&fan[i])==0){
                        dp[j|fan[i]]=min(dp[j]+1,dp[j|fan[i]]);
                    }
                }
            }
            printf("Scenario #%d:
    ",c++);
            printf("%d
    
    ",dp[zhi-1]);
        }
      return 0;
    }

    I题-Buy the souvenirs

    返回列表

    题意:

    输入n,m

    有n个硬币

    给n个价值为ai的硬币,求最多个数的硬币,其中价值不超过m的有多少种。如果没有输出Sorry, you can't buy anything.

    思路:

    dp【i】【j】i表示个数,j表示价值,如果dp【i-1】【j-ai】>0,那么dp【i】【j】+=dp【i-1】【j-ai】

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    const int maxn=1e5+10;
    int t,n,m,a;
    int dp[40][510];
    int main(){
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            for(it i=1;i<=n;i++){ scanf("%d",&a);
                for(it j=m;j>=a;j--)
                    for(it k=i;k>=1;k--)
                        if(dp[k-1][j-a]>0)
                            dp[k][j]+=dp[k-1][j-a];
            }
            int f=0,sum=0;
            for(it i=n;i>=1;i--){
                for(it j=0;j<=m;j++){sum+=dp[i][j];}
                if(sum>0){
                    printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.
    ",sum,i);f=1;break;
                }
    
            }
            if(!f){printf("Sorry, you can't buy anything.
    ");}
        }
      return 0;
    }

    待补

    D - Cash Machine

    题意:

    有n大小的钱包,有m种硬币,每种硬币有个数和价值,钱包里最多能放价值多少的硬币,不能超过n

    思路:

    完全背包,需要记录使用个数,或者二进制优化01背包

    完全背包

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    const int maxn=1e5+10;
    ll ksm(ll a,ll b){if(b<0)return 0;ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans;}
    int t,n,pos,m;
    int dp[maxn],a[20][2],num[maxn];
    int main() {
        while(~scanf("%d%d",&m,&n)){
          for(it i=0;i<n;i++){
            scanf("%d%d",&a[i][0],&a[i][1]);
          }
          mem(dp,0);
          for(it i=0;i<n;i++){
              mem(num,0);
              for(it j=a[i][1];j<=m;j++){
                  if(dp[j]<dp[j-a[i][1]]+a[i][1] && num[j-a[i][1]]<a[i][0]){
                     dp[j]=dp[j-a[i][1]]+a[i][1];
                     num[j]=num[j-a[i][1]]+1;
                  }
              }
          }
          printf("%d
    ",dp[m]);
        }
        return 0;
    }

    二进制优化

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    const int maxn=1e5+10;
    ll ksm(ll a,ll b){if(b<0)return 0;ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans;}
    int n,pos,m,cnt;
    int dp[maxn],a[20][2],t[maxn];
    int main() {
        while(~scanf("%d%d",&m,&n)){cnt=0;
          for(it i=0;i<n;i++){
            scanf("%d%d",&a[i][0],&a[i][1]);
            int k=1;
            if(a[i][0]==0||a[i][1]==0)continue;
            while(a[i][0]-k>0){
                t[cnt++]=k*a[i][1];
                a[i][0]-=k;
                k*=2;
            }
            t[cnt++]=a[i][0]*a[i][1];
          }
          mem(dp,0);
          for(it i=0;i<cnt;i++){
              for(it j=m;j>=t[i];j--){
                  if(dp[j]<dp[j-t[i]]+t[i]){
                     dp[j]=dp[j-t[i]]+t[i];
                  }
              }
          }
          printf("%d
    ",dp[m]);
        }
        return 0;
    }

    C - Investment

    题意:

    给出n,n组测试;给出最初的本金,年数;

    给出d,d组银行(物品)以及每组银行的存入钱数和利息(所占容量及价值),求出几年后的最大价值。

    思路:

    完全背包

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define il inline
    #define it register int
    #define inf 0x3f3f3f3f
    #define lowbit(x) (x)&(-x)
    #define pii pair<int,int>
    #define mak(n,m) make_pair(n,m)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mod 998244353
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    const int maxn=1e5+10;
    ll ksm(ll a,ll b){if(b<0)return 0;ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans;}
    int n;
    int amount,y;
    int d;
    int weight[12],value[12];
    int dp[1000002];
    int main() {
       scanf("%d",&n);
        while(n--){
            scanf("%d%d",&amount,&y);
            scanf("%d",&d);
            for (int i = 0; i < d; i += 1){
                scanf("%d%d",&weight[i],&value[i]);
                weight[i] /= 1000;
            }
            mem(dp,0);
            for (int i = 0; i < y; i ++){
                int tem = amount/1000;
                for (int j = 0; j < d; j ++){
                    for (int k = weight[j]; k <= tem; k += 1){
                        dp[k] = max(dp[k],dp[k-weight[j]]+value[j]);
                    }
                }
                amount += dp[tem];
            }
            printf("%d
    ",amount);
        }
        return 0;
    }
  • 相关阅读:
    vCenter添加主机后添加虚拟机失败
    FreeSwitch那些坑之CallCenter
    FreeSwitch录音功能
    在Widnwos中安装VMware vCenter Server
    VMware配置额外内存设置
    VMWare全局禁用vmem虚拟内存文件
    MySQL实现高可用架构之MHA
    Dell Vostro 5590在Windows 10中WIFI经常断开
    tesseract-OCR + pytesseract安装
    python3 TensorFlow训练数据集准备 下载一些百度图片 入门级爬虫示例
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/12540229.html
Copyright © 2020-2023  润新知