每日两刷(Erwin Schrödinger的橘猫(字典树或map),冰水挑战(dfs或dp),分宿舍(dp,枚举)2019/4/13)

由于题目主人有隐私,不方便贴出题目

题目大意:

n串密码,然后k组输入,当输入的是其中一个密码的前面几位或者整串密码时,可以成功解锁。

思路:

做法1:
暴力存入set中,然后搜索即可。

代码:
#include<iostream>
#include<cstdio>
#include <string.h>
#include <map>
using namespace std;
#define ll long long

map<string,bool>m;
map<string,bool>::iterator it;
char a[13];
int main(){
    int t;
    cin>>t;
    while(t--){
    scanf("%s",a);
    string num;
    for(int i=0;i<strlen(a);i++){
          num+=a[i];
          it=m.find(num);
          if(it==m.end())
          m.insert(make_pair(num,1));
        }
    }
    int b,o=1;
    scanf("%d",&b);
    while(b--){
        string k;
        cin>>k;
          it=m.find(k);
        printf("Case #%d:\n",o++);
        if(it!= m.end()) printf("YES\n");
        else printf("NO\n");
    }
}

做法2:
字典树(模板题,详解请看 https://blog.csdn.net/qq_43333395/article/details/89289170 )

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int trie[400001][15],len,root,tot,sum[400001];
bool p;
int n,m;
char s[11];
void insert()
{
    len=strlen(s);
    root=0;
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'0';
        if(!trie[root][id]) trie[root][id]=++tot;
        sum[trie[root][id]]++;//前缀保存
        root=trie[root][id];
    }
}
int search()
{
    root=0;
    len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'0';
        if(!trie[root][id]) return 0;
        root=trie[root][id];
    }//root经过此循环后变成前缀最后一个字母所在位置
    return 1;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        insert();
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        cin>>s;
        printf("%d\n",search());
    }
}

冰水挑战

Polar Bear Pitching helps you crystallize your message.
The stage could not be any cooler, and we mean literally:
a hole cut through the ice in the frozen Baltic Sea.

2050有一项很有挑战的活动 —— Polar Bear Pitching 。
体验人跳入冰水中讲述自己的恐惧,改变以及梦想。这是没有时间限制的演讲,就看你能在冰水中呆多久!

现在,我们要依次面对 n 个冰水挑战,每个挑战你都可以选择接受或不接受。接受第 i 个挑战会让你丧失 ai点体力,因为每个挑战所处的环境不同,如果你要挑战它,在挑战它之前你的体力 x 会变成 min(x,bi),当你完成这个挑战的时候,你的体力会变成 x−ai,体力任何时候不允许小于等于 0,无论你是否接受第 i 个挑战,在这个挑战结束以后你的体力都会增加 ci。

现在我们想知道最多可以完成多少个挑战。

Input

第一行一个正整数 T (T≤50) 表示数据组数。

接下来 T 组数据,每组第一行两个正整数 n,c (1≤n≤103,1≤c≤109),表示挑战的数量和初始体力,接下来 n 行,每行三个非负整数 ai,bi,ci(0≤ai,bi,ci≤109)。

Output

对于每组数据输出一行一个数,表示你最多能完成几个挑战。

Sample Input

2
3 10
1 2 0
4 8 3
6 10 1
2 1
1 1 1
1 1 1

Sample Output

2
0
暴力dfs哈哈

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
ll a[1005],b[1005],c[1005];

ll dp[1005][1005];
ll n,x;
int ans=0;
void dfs(int i,int j,ll x){
    if(dp[i][j]>=x)
        return;
    dp[i][j]=x;
    if(i==n+1){
        ans=max(ans,j);
        return;
    }
    if(min(x,b[i])-a[i]>0)
        dfs(i+1,j+1,min(x,b[i])-a[i]+c[i]);
    dfs(i+1,j,x+c[i]);
    return;
}

int main(){
 int t;
 cin>>t;
 while(t--){
    ans=0;
    memset(dp,-1,sizeof(dp));
    scanf("%lld %lld",&n,&x);
    for(int i=1;i<=n;i++){
        scanf("%lld %lld %lld",&a[i],&b[i],&c[i]); }
        dfs(1,0,x);
        printf("%d\n",ans);

 }
}

分宿舍

“那天TA说TA要来,于是我就来啦。
那天我说我要来,于是你就来啦。
TA看到了什么?
你又看到了什么?
我看到你们在一起,我是真的很happy:)
太阳在哪里啊?
就在早上七八点。
太阳在哪里啊?
就在云的栖息地!”
——2050主题曲

2050的线下活动吸引了很多心怀梦想的年轻人。

小伙们打算组团去参加。他们一共有 n+m+2k 个人,包括 n+k 个男生,m+k 个女生,其中 k 对男女生为异性情侣,现在他们要找房间住。房间有三种类型,双人间 a 元一间,三人间 b 元一间,这两种只能同性一起住。情侣间能住一对异性情侣,一间 c 元。除了情侣间以外,其他房间都可以不住满。

求最少花多少钱,能让小伙伴们都有地方住。

Input

第一行一个整数 T (1≤T≤50) 表示数据组数。

接下来 T 组数据,每组数据一行 6 个整数 n,m,k,a,b,c,其中 0≤n,m,k≤103,0≤a,b,c≤109

Output

对于每组数据输出一行一个数,表示所有人住下来所需要的最小花费。

Sample Input

2
3 0 1 1 3 3
3 3 2 1 6 2

Sample Output

3
6
大佬说是dp或者直接考虑最优策略枚举。
考虑性价比分间,然后再考虑要不要拆开一个小的变成大的或者一个大的变成小的。
自己写了一个dp,不知道正确不正确。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll T,n,m,k,a,b,c;
ll dp[3005][3005][3];

int main(){
     cin>>T;
     while(T--){
        ll sum=0;
        scanf("%lld %lld %lld %lld %lld %lld",&n,&m,&k,&a,&b,&c);
        int o=0;
        if(a*3<=b*2&&a<=c) o=1; //优先考虑a
        if(a*3>b*2&&b*2<c*3) o=2; //优先考虑b
        if(a>c&&b*2>c*3) o=3;    //优先考虑c
        if(o==1){
           sum+=(k/2)*a*2;
           k=k%2;
        }
        if(o==2){
            sum+=(k/3)*b*2;
            k=k%3;
        }
        if(o==3){
            sum+=k*c;
            k=0;
        }
            memset(dp,0x3f3f3f3f,sizeof(dp));
            dp[n][m][k]=0;
            for(int i=n;i<=n+3;i++){
            for(int j=m;j<m+3;j++)
                for(int l=k;l<=k+3;l++){
                    dp[i][j][l]=0;
                }
            }
        for(int i=n;i>=0;i--){
            for(int j=m;j>=0;j--){
                for(int l=k;l>=0;l--){
                 if(dp[i][j][l]>dp[i+2][j][l]+a){      //男买a
                      dp[i][j][l]=dp[i+2][j][l]+a;
                 }
                 if(dp[i][j][l]>dp[i][j+2][l]+a){      //女买a
                    dp[i][j][l]=dp[i][j+2][l]+a;
                 }
                 if(dp[i][j][l]>dp[i][j][l+1]+c){       //情侣买c
                    dp[i][j][l]=dp[i][j][l+1]+c;
                 }
                 if(dp[i][j][l]>dp[i+1][j+1][l+1]+2*a){     //情侣分开买a
                    dp[i][j][l]=dp[i+1][j+1][l+1]+2*a;
                 }
                 if(dp[i][j][l]>dp[i+2][j+2][l+1]+2*b){    //情侣分开买b
                    dp[i][j][l]=dp[i+2][j+2][l+1]+2*b;
                 }
                 if(dp[i][j][l]>dp[i+3][j][l]+b){      //男买b
                      dp[i][j][l]=dp[i+3][j][l]+b;
                 }
                 if(dp[i][j][l]>dp[i][j+3][l]+b){      //女买b
                    dp[i][j][l]=dp[i][j+3][l]+b;
                 }
                }
            }
        }
        /*for(int i=n;i>=0;i--)
            for(int j=m;j>=0;j--)
                for(int l=k;l>=0;l--){
                    printf("%d %d %d %lld ",i,j,l,dp[i][j][l]);
                    if(l==0) cout<<endl;
                    if(j==0) cout<<endl;
                    } */
        cout<<dp[0][0][0]+sum<<endl;
    }
}

官方题解出来啦:

#include<stdio.h>
#include<cstring>
Code ( ):
#include<algorithm>
#include<vector>
#include<map>
#include<assert.h>
#include<set>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<iostream>
#include<bitset>
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define rep(i,j,k) for(int i=(int)(j);i<=(int)(k);i++)
#define per(i,j,k) for(int i=(int)(j);i>=(int)(k);i--)
using namespace std;
typedef long long LL;
typedef double db;
const int N=3225;
int n,m,k;LL a,b,c;
LL f[N];
void Main(){
 scanf("%d%d%d%lld%lld%lld",&n,&m,&k,&a,&b,&c);
 assert(0<=n&&n<=1000);
 assert(0<=m&&m<=1000);
 assert(0<=k&&k<=1000);
 assert(0<=a&&a<=1000000000);
 assert(0<=b&&b<=1000000000);
 assert(0<=c&&c<=1000000000);
 rep(i,0,n+k+m+20)f[i]=(1ll<<60);
 f[0]=0;
 rep(i,2,n+k+m+20)f[i]=min(f[i],f[i-2]+a);//背包,物品体积为2,费⽤为a
 rep(i,3,n+k+m+20)f[i]=min(f[i],f[i-3]+b);//背包,物品体积为3,费⽤为b
 per(i,n+k+m+19,0)f[i]=min(f[i],f[i+1]); //考虑不住满的情况
 LL ans=1ll<<60;
 rep(i,0,k)ans=min(ans,i*1ll*c+f[n+k-i]+f[m+k-i]); //枚举情侣房个数,计算
答案
 printf("%lld\n",ans);
}
int main(){
 int t;scanf("%d",&t);
 assert(1<=t&&t<=50);
 while(t--)Main();
 return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43333395/article/details/89288492