zoukankan      html  css  js  c++  java
  • AYIT609暑假集训第一周下训练题题解

    Changing Digits

    来源:POJ - 3373

    题意:
    现在给你两个数n , k. 要求一个新的数m
    满足四个要求:
    1、m没有前导0和长度和n一样长.
    2、可以被k整除.
    3、满足1,2的前提下, 尽量满足m和n的每位尽量相同.
    4、满足1,2,3的前提下, 使m最小.

    AC代码:

    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<stdio.h>
    #include<cmath>
    #include<list>
    #include<stdlib.h>
    #include<map>
    #include<stacp>
    #include<stdio.h>
    #include<queue>
    
    using namespace std;
    typedef long long ll;
    #define sc(T) scanf("%d",&T)
    #define scc(x,y) scanf("%d %d",&x,&y)
    #define pr(T) printf("%d
    ",T)
    #define f(a,b,c) for (int a=b;a<=c;a++)
    #define ff(a,b,c) for (int a=b;a>=c;a--)
    #define inf 0x3f3f3f3f
    #define mem(a,b) memset(a,b,sizeof(a))
    #define eps 1e-9
    #define PI acos(-1)
    
    const int N=129;
    int p,L,Mod,rem[N][N*N],ans[N],num[N],mod[N][12];
    char s[N];
    
    bool dfs(int L,int pos,int M)
    {
        if(M==0)//余数为0得到解
        {
            for(int i=L-1;i>=0;--i)
                printf("%d",ans[i]);
            printf("
    ");
            return 1;
        }
        if(L==0||rem[L][M]>pos)
            return 0;//关键剪枝
        for(int i=pos;i>=0;i--) //搜索比N小的从高位开始
        {
            for(int j=0;j<num[i];j++)
            {
                if(i==L-1&&j==0)
                    continue;
                ans[i]=j;
                int tmp=M-(mod[i][num[i]]-mod[i][j]);
                tmp%=p;
                if(tmp<0)
                    tmp+=p;
                if(dfs(L-1,i-1,tmp))
                    return 1;
            }
            ans[i]=num[i];
        }
        for(int i=0;i<=pos;i++)//搜索比n大的从低位开始
        {
            for(int j=num[i]+1;j<10;j++)
            {
                ans[i]=j;
                int tmp=M+mod[i][j]-mod[i][num[i]];
                tmp%=p;
                if(tmp<0)
                    tmp+=p;
                if(dfs(L-1,i-1,tmp))
                    return 1;
            }
            ans[i]=num[i];
        }
        rem[L][M]=pos+1;
        return 0;
    }
    
    int main()
    {
        while(~scanf("%s",s))
        {
            scanf("%d",&p);
            L=strlen(s);
            mem(rem,0);
            for(int i=0;i<10;++i)
                mod[0][i]=i%p;
            for(int i=1;i<L;++i)
            {
                for(int j=0;j<10;++j)
                    mod[i][j]=(mod[i-1][j]*10)%p;
            }
            Mod=0;//计算s模p的余数,将s倒置
            for(int i=0;i<L;++i)
            {
                ans[i]=num[i]=s[L-i-1]-'0';
                Mod+=mod[i][num[i]];
                Mod%=p;
            }
            for(int i=0;i<=L;++i)
            {
                if(dfs(i,L-1,Mod))
                    break;
            }
        }
        return 0;
    }
    

    How many ways

    来源:HDU - 1978

    记忆化搜索AC代码:

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int a[110][110];
    int b[110][110];
    int n,m;
    int dfs(int x,int y)
    {
        if(b[x][y]>=0)
            return b[x][y];
        b[x][y]=0;
        for(int i=0; i<=a[x][y]; i++)
        {
            for(int j=0; j<=a[x][y]-i; j++)
            {
                int tx=x+i;
                int ty=y+j;
                if(tx<0||ty<0||tx>=n||ty>=m)
                    continue;
                b[x][y]=(b[x][y]+dfs(tx,ty))%10000;
            }
        }
        return b[x][y];
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            memset(a,0,sizeof(a));
            memset(b,-1,sizeof(b));
            scanf("%d%d",&n,&m);
            for(int i=0; i<n; i++)
                for(int j=0; j<m; j++)
                    scanf("%d",&a[i][j]);
            b[n-1][m-1]=1;
            printf("%d
    ",dfs(0,0));
        }
        return 0;
    }
    

    dp AC代码:

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<string.h>
    #include<queue>
    #include<iostream>
    #include<stack>
    using namespace std;
    typedef long long ll;
    const int mod=1e4;
    
    int a[110][110],dp[110][110];
    
    int main()
    {
        int t,n,m;
        cin>>t;
        while(t--)
        {
            memset(dp,0,sizeof(dp));
            cin>>n>>m;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    cin>>a[i][j];
                }
            }
            dp[n][m]=1;
            for(int i=n;i>=1;i--)
            {
                for(int j=m;j>=1;j--)
                {
                    for(int p=0;p<=a[i][j]&&(i+p<=n);p++)
                    {
                        int ww=a[i][j]-p;
                        for(int q=0;q<=ww&&(j+q<=m);q++)
                        {
                            if(p==0&&q==0)
                                continue;
                            dp[i][j]=(dp[i][j]+dp[i+p][j+q])%mod;
                        }
                    }
                }
            }
            int w=dp[1][1];
            printf("%d
    ",w);
        }
        return 0;
    }
    

    B-number

    来源:HDU - 3652

    题意:
    求1~N中包含13且能被13整除的数的数量。

    思路:
    dp[i][j][k],i表示位数,j表示余数,k表示末尾是1、末尾不是1、含有13.。
    数位dp模板题。

    AC代码:

    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<stdio.h>
    #include<cmath>
    #include<list>
    #include<stdlib.h>
    #include<map>
    #include<stacp>
    #include<stdio.h>
    #include<queue>
    
    using namespace std;
    typedef long long ll;
    #define sc(T) scanf("%d",&T)
    #define scc(x,y) scanf("%d %d",&x,&y)
    #define pr(T) printf("%d
    ",T)
    #define f(a,b,c) for (int a=b;a<=c;a++)
    #define ff(a,b,c) for (int a=b;a>=c;a--)
    #define inf 0x3f3f3f3f
    #define mem(a,b) memset(a,b,sizeof(a))
    #define eps 1e-9
    #define PI acos(-1)
    
    const int N=15;
    int a[N],dp[N][N][3];
    
    int dfs(int pos,int pre,int mod,int limit)
    {
        if(pos==-1)
            return (pre==2&&!mod);
        if(!limit&&dp[pos][mod][pre]!=-1)
            return dp[pos][mod][pre];
        int up=limit?a[pos]:9;
        int tmp=0;
        for(int i=0;i<=up;i++)
        {
            int tmod=(mod*10+i)%13;
            if((pre==1&&i==3)||pre==2)
                tmp+=dfs(pos-1,2,tmod,limit&&a[pos]==i);
            else
                tmp+=dfs(pos-1,i==1,tmod,limit&&a[pos]==i);
        }
        if(!limit)
            dp[pos][mod][pre]=tmp;
        return tmp;
    }
    
    int solve(int x)
    {
        int pos=0;
        while(x)
        {
            a[pos++]=x%10;
            x/=10;
        }
        return dfs(pos-1,0,0,1);
    }
    
    int main()
    {
        int n;
        memset(dp,-1,sizeof(dp));
        while(cin>>n)
            printf("%d
    ",solve(n));
        return 0;
    }
    

    Cash Machine

    来源:POJ - 1276

    题意:给出几组不同数量不同面值的钱币,给你一个cash,要你求出不超过cash的金额。

    思路:多重背包模板题。

    AC代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<iomanip>
    #include<string.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int w[100020];
    int dp[100020];
    int main()
    {
        std::ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
        int cash;
        int a,b;
        while(cin>>cash)
        {
            memset(w,0,sizeof(w));
            memset(dp,0,sizeof(dp));
            int n;
            cin>>n;
            int p=0;
            for(int i=0;i<n;i++)
            {
                cin>>a>>b;
                int x=1;
                while(x<a)
                {
                    w[p++]=x*b;
                    a=a-x;
                    x*=2;
                }
                if(a)
                    w[p++]=a*b;
            }
            for(int i=0;i<p;i++)
            {
                for(int j=cash;j>=w[i];j--)
                    dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
            }
            cout<<dp[cash]<<endl;
        }
        return 0;
    }
    

    饭卡

    来源:HDU - 2546

    思路:01背包模板题

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    int a[1010],dp[1010];
    
    int main()
    {
        int n,m;
        while(~scanf("%d",&n)&&n)
        {
            memset(dp,0,sizeof(dp));
            for(int i=0; i<n; i++)
                scanf("%d",&a[i]);
            scanf("%d",&m);
            if(m>=5)
            {
                sort(a,a+n);
                for(int i=0; i<n-1; i++)
                {
                    for(int j=m-5; j>=a[i]; j--)
                        dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
                }
                printf("%d
    ",m-a[n-1]-dp[m-5]);
            }
            else
                printf("%d
    ",m);
        }
        return 0;
    }
    

    Robberies

    来源:HDU - 2955

    题意:
    小偷去100家银行,偷每家都有被抓概率被抓,概率p[i],偷不同银行的事件之间相互独立。
    现在小偷希望偷到更多的钱,但是被抓的概率不能超过P,问最多能偷多少钱。

    思路:
    01背包一点点变形。

    AC代码:

    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<stdio.h>
    #include<cmath>
    #include<list>
    #include<stdlib.h>
    #include<map>
    #include<stacp>
    #include<stdio.h>
    #include<queue>
    
    using namespace std;
    typedef long long ll;
    #define sc(T) scanf("%d",&T)
    #define scc(x,y) scanf("%d %d",&x,&y)
    #define pr(T) printf("%d
    ",T)
    #define f(a,b,c) for (int a=b;a<=c;a++)
    #define ff(a,b,c) for (int a=b;a>=c;a--)
    #define inf 0x3f3f3f3f
    #define mem(a,b) memset(a,b,sizeof(a))
    #define eps 1e-9
    #define PI acos(-1)
    
    double dp[500010],w[1010];
    int v[1010];
    
    int main()
    {
        int n;
        sc(n);
        while(n--)
        {
            mem(dp,0);
            dp[0]=1;
            int a,sum=0;
            double p;
            scc(p,a);
            p=1-p;
            for(int i=1;i<=a;i++)
            {
                scc(v[i],w[i]);
                w[i]=1-w[i];
                sum+=v[i];
            }
            for(int i=1;i<=a;i++)
            {
                for(int j=sum;j>=v[i];j--)
                    dp[j]=max(dp[j-v[i]]*w[i],dp[j]);
            }
            for(int i=sum;i>=0;i--)
            {
                if(dp[i]>p)
                {
                    cout<<i<<endl;
                    break;
                }
            }
        }
        return 0;
    }
    

    Dividing

    来源:POJ - 1014

    题意:
    有价值为1~6的6个宝石,给出每种价值的宝石数量,问是是否能选出部分,使选出部分的价值是总价值的一半。

    思路:
    多重背包模板题,可以加个二进制优化一下。

    AC代码:

    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<stdio.h>
    #include<cmath>
    #include<list>
    #include<stdlib.h>
    #include<map>
    #include<stacp>
    #include<stdio.h>
    #include<queue>
    
    using namespace std;
    typedef long long ll;
    #define sc(T) scanf("%d",&T)
    #define scc(x,y) scanf("%d %d",&x,&y)
    #define pr(T) printf("%d
    ",T)
    #define f(a,b,c) for (int a=b;a<=c;a++)
    #define ff(a,b,c) for (int a=b;a>=c;a--)
    #define inf 0x3f3f3f3f
    #define mem(a,b) memset(a,b,sizeof(a))
    #define eps 1e-9
    #define PI acos(-1)
    
    const int N=1e6+20;
    int a[10],b[N];
    bool dp[N];
    
    int main()
    {
        int cas=0;
        while(~scanf("%d %d %d %d %d %d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6]))
        {
            if(a[1]+a[2]+a[3]+a[4]+a[5]+a[6]==0)
                break;
            int sum=0;
            for(int i=1;i<=6;i++)
                sum+=a[i]*i;
            printf("Collection #%d:
    ",++cas);
            if(sum&1)
            {
                printf("Can't be divided.
    
    ");
                continue;
            }
            int cnt=0;
            for(int i=1;i<=6;i++)
            {
                int j=0;
                while(a[i]>=(1<<j))
                {
                    b[++cnt]=(1<<j)*i;
                    a[i]-=(1<<j);
                    j++;
                }
                if(a[i]>0)
                    b[++cnt]=a[i]*i;
            }
            int mid=sum/2;
            for(int i=0;i<=mid;i++)
                dp[i]=0;
            dp[0]=1;
            for(int i=1;i<=cnt;i++)
            {
                for(int j=mid;j>=b[i];j--)
                {
                    if(dp[j-b[i]])
                        dp[j]=1;
                }
            }
            if(dp[mid])
                printf("Can be divided.
    ");
            else
                printf("Can't be divided.
    ");
            printf("
    ");
        }
        return 0;
    }
    

    悼念512...

    悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
    来源:HDU - 2191

    思路:多重背包模板题。

    AC代码:

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<string.h>
    #include<queue>
    #include<iostream>
    #include<stack>
    using namespace std;
    typedef long long ll;
    
    int dp[110],pr[110],w[110],d[110];
    
    int main()
    {
        int t,sum,m;
        cin>>t;
        while(t--)
        {
            memset(dp,0,sizeof(dp));
            cin>>sum>>m;
            for(int i=0; i<m; i++)
                cin>>pr[i]>>w[i]>>d[i];
            for(int i=0; i<m; i++) //种类
            {
                for(int j=0; j<d[i]; j++)//袋数
                {
                    for(int k=sum; k>=pr[i]; k--)
                    {
                        dp[k]=max(dp[k],dp[k-pr[i]]+w[i]);
                    }
                }
            }
            printf("%d
    ",dp[sum]);
    
    //        for(int i=0;i<m;i++)
    //        {
    //            for(int j=0;j<w[i];j++)
    //            {
    //                for(int k=0;k<=d[i];k++)
    //                {
    //                    if(k*w[i]<=sum)
    //                        dp[i][j]=max(dp[i-1][j-k*w[i]]+k*v[i],dp[i-1][j]);
    //                    else
    //                        dp[i][j]=dp[i-1][j];
    //                }
    //
    //            }
    //        }
    //        printf("%d
    ",dp[m][])
        }
        return 0;
    }
    
  • 相关阅读:
    在dataGridView中实现批量删除
    VS2005制作简单的安装程序
    [WinForms]
    TreeView的联动复选框
    TreeView
    AcceptChanges()和RejectChanges()
    用C#在WINDOWS中实现新用户帐号的创建
    测试成功的窗体应用[批量新增、删除、保存]
    TreeView的递归读取
    VS2005中部署C#应用程序
  • 原文地址:https://www.cnblogs.com/OFSHK/p/13377429.html
Copyright © 2011-2022 走看看