• 2016-6-19 动态规划,贪心算法练习


    DP:1.codevs 1493 糖果

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 黄金 Gold
     
    题目描述 Description

    最近小修很高兴,因为她的k个外甥就要来她家里玩了。她上超市买了一大堆糖果,总共有n颗。

    小修准备把所有的糖果分成k堆(当然每一堆至少要有一颗糖果)。可是到底有多少种分法呢?

    她冥思苦想不得其解,你能帮助她吗?

    输入描述 Input Description

    两个用空格分开的整数n, k(n<=60000, k<=100)。

    输出描述 Output Description

    仅一个数:方案总数。

    注意:因为方案数可能很多,你仅需要输出结果mod 10000的值。

    样例输入 Sample Input

    4 2

    样例输出 Sample Output

    2

     1 #define N 60005
     2 #define K 105
     3 #include<iostream>
     4 using namespace std;
     5 #include<cstdio>
     6 #define mod 10000
     7 int n,k;
     8 int f[N][K];
     9 int main()
    10 {
    11     scanf("%d%d",&n,&k);
    12     for(int i=1;i<=n;++i)
    13       for(int j=1;j<=i&&j<=k;++j)
    14       {
    15           if(j==1)
    16            f[i][j]=1;
    17           else f[i][j]=(f[i-1][j-1]+f[i-j][j])%mod;
    18       }
    19     printf("%d
    ",f[n][k]);
    20     return 0;
    21 }

    贪心:2.1052 地鼠游戏

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
    题目描述 Description

        王钢是一名学习成绩优异的学生,在平时的学习中,他总能利用一切时间认真高效地学习,他不但学习刻苦,而且善于经常总结、完善自己的学习方法,所以他总能在每次考试中得到优异的分数,这一切很大程度上是由于他是一个追求效率的人。

        但王钢也是一个喜欢玩的人,平时在学校学习他努力克制自己玩,可在星期天他却会抽一定的时间让自己玩一下,他的爸爸妈妈也比较信任他的学习能力和学习习惯,所以在星期天也不会象其他家长一样对他抓紧,而是允许他在星期天上午可以自由支配时间。

        地鼠游戏是一项需要反应速度和敏捷判断力的游戏。游戏开始时,会在地板上一下子冒出很多地鼠来,然后等你用榔头去敲击这些地鼠,每个地鼠被敲击后,将会增加相应的游戏分值。问题是这些地鼠不会傻傻地等你去敲击,它总会在冒出一会时间后又钻到地板下面去(而且再也不上来),每个地鼠冒出后停留的时间可能是不同的,而且每个地鼠被敲击后增加的游戏分值也可能是不同,为了胜出,游戏参与者就必须根据每个地鼠的特性,有选择地尽快敲击一些地鼠,使得总的得分最大。

    这个极具挑战性的游戏王钢特别喜欢,最近他经常在星期天上午玩这个游戏,慢慢地他不但敲击速度越来越快(敲击每个地鼠所需要的耗时是1秒),而且他还发现了游戏的一些特征,那就是每次游戏重新开始后,某个地鼠冒出来后停留的时间都是固定的,而且他记录了每个地鼠被敲击后将会增加的分值。于是,他在每次游戏开始后总能有次序地选择敲击不同的地鼠,保证每次得到最大的总分值。

    输入描述 Input Description

        输入包含3行,第一行包含一个整数n(1<=n<=100)表示有n个地鼠从地上冒出来,第二行n个用空格分隔的整数表示每个地鼠冒出后停留的时间,第三行n个用空格分隔的整数表示每个地鼠被敲击后会增加的分值(<=100)。每行中第i个数都表示第i个地鼠的信息。

    输出描述 Output Description

        输出只有一行一个整数,表示王钢所能获得的最大游戏总分值。

    样例输入 Sample Input

    5

    5  3  6  1  4

    7  9  2  1  5

    样例输出 Sample Output

    24

    /*一开始理解错了,以为是个线段覆盖,后来发现线段只有上下界,具体的端点是没有的。
    贪心法:处理出每个点在最大停留时间的剩余时间,先处理剩余时间少的,也就是在一个地鼠即将下地的前一秒敲它。如果有同样好几个时间少,就取分数最大的。
    */
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #include<algorithm>
    #define N 132
    struct Ds{
        int tim,fs;
        bool operator<(Ds p)
        const{return tim<p.tim;}
    }ds[120];
    int n,maxsytim=0,ans=0,sum;
    bool visit[N];
    void input()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&ds[i].tim);
            sum=max(sum,ds[i].tim);
        }
        for(int i=1;i<=n;++i)
        {
            ds[i].tim=sum-ds[i].tim;
            maxsytim=max(maxsytim,ds[i].tim);
        }
        for(int i=1;i<=n;++i)
        scanf("%d",&ds[i].fs);
          
    }
    int main()
    {
        input();
        sort(ds+1,ds+n+1);
        for(int j=0;j<sum;++j)/*注意sum这里不是maxsysum,因为这个不是敲地鼠的总时间,而且要小于sum,因为敲一个地鼠需要一秒钟*/
        {
            int temp,kkk=0;
            for(int i=1;i<=n;++i)
            {
                if(ds[i].tim<=j&&!visit[i]&&ds[i].fs>kkk)
                {
                    kkk=ds[i].fs;
                    temp=i;
                }
    
            }
            visit[temp]=true;
            ans+=kkk;
        }
        printf("%d",ans);
        return 0;
    }

    3.NOI 1757:神奇的口袋

    总时间限制: 
    10000ms
     
    内存限制: 
    65536kB
    描述
    有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。John现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品。现在的问题是,John有多少种不同的选择物品的方式。
    输入
    输入的第一行是正整数n (1 <= n <= 20),表示不同的物品的数目。接下来的n行,每行有一个1到40之间的正整数,分别给出a1,a2……an的值。
    输出
    输出不同的选择物品的方式的数目。
    样例输入
    3
    20
    20
    20
    
    样例输出
    3
    #include<iostream>
    using namespace std;
    #include<cstdio>
    int n;
    int a[25];
    int f[45]={0};
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
          scanf("%d",&a[i]);
        f[0]=1;
        for(int i=1;i<=n;++i)
          for(int j=40;j>=a[i];--j)
          f[j]+=f[j-a[i]];
        printf("%d
    ",f[40]);
        return 0;
    }

    4.NOI 2393:Going to the Movies

    总时间限制: 
    10000ms
     
    单个测试点时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述
    Farmer John is taking some of his cows to the movies! While his truck has a limited capacity of C (100 <= C <= 5000) kilograms, he wants to take the cows that, in aggregate, weigh as much as possible without exceeding the limit C.

    Given N (1 <= N <= 16) cows and their respective weights W_i, determine the weight of the heaviest group of cows that FJ can take to the movies.
    输入
    * Line 1: Two space-separated integers: C and N

    * Lines 2..N+1: Line i+1 contains a single integer: W_i
    输出
    * Line 1: A single integer that is the weight of the heaviest group of cows that can go to the movies
    样例输入
    259 5
    81
    58
    42
    33
    61
    
    样例输出
    242
    
    提示
    81+58+42+61 = 242;
    this is the best possible sum
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define C 5101
    bool f[C]={0};
    int n,c;
    int w[20];
    int main()
    {
        scanf("%d%d",&c,&n);
        for(int i=1;i<=n;++i)
          scanf("%d",&w[i]);
        f[0]=true;
        for(int i=1;i<=n;++i) 
          for(int j=c;j>=w[i];--j)
          f[j]=f[j]||f[j-w[i]];
        for(int j=c;j>=0;--j)
        {
            if(f[j])
            {
                printf("%d
    ",j);
                break;
            }
        }
        return 0;
    }

    5.NOI 7624:山区建小学

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < m。为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设 0 < n < = m < 500 )。请根据给定的m、n以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值。

    输入
    第1行为m和n,其间用空格间隔
    第2行为(m-1) 个整数,依次表示从一端到另一端的相邻村庄的距离,整数之间以空格间隔。

    例如
    10 3
    2 4 6 5 2 4 3 1 3
    表示在10个村庄建3所学校。第1个村庄与第2个村庄距离为2,第2个村庄与第3个村庄距离为4,第3个村庄与第4个村庄距离为6,...,第9个村庄到第10个村庄的距离为3。
    输出
    各村庄到最近学校的距离之和的最小值。
    样例输入
    10 2
    3 1 3 1 1 1 1 1 3
    样例输出
    18
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #define N 523
    int sum[N],w[N],n,m;
    int f[N][N],p[N][N]={0};
    void input()
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m-1;++i)
        {
            scanf("%d",&w[i]);
        }
        sum[1]=0;
        for(int i=2;i<=m;++i)
        sum[i]=sum[i-1]+w[i-1];
        for(int i=1;i<=m;++i)
          for(int j=i;j<=m;++j)
          {
              int mid=(i+j)>>1;
              for(int l=i;l<=j;++l)
              p[i][j]+=abs(sum[l]-sum[mid]);
          }
        memset(f,99,sizeof(f));
        for(int i=1;i<=m;++i)
          f[i][1]=p[1][i];
    }
    void dp()
    {
        for(int j=2;j<=n;++j)
          for(int i=j;i<=m;++i)
            for(int k=j-1;k<=i-1;++k)
            f[i][j]=min(f[i][j],f[k][j-1]+p[k+1][i]);
    }
    int main()
    {
        input();
        dp();
        printf("%d
    ",f[m][n]);
        return 0;
    }

    6.cojs 1507. [IOI2000]邮局

    ★☆   输入文件:postoffice.in   输出文件:postoffice.out   简单对比
    时间限制:1 s   内存限制:256 MB

    【题目描述】

    有一条笔直的高速公路,路旁分布着一些村庄。公路可以用一条数轴表示,则村庄的位置就是其坐标。没有两个村庄的坐标相同。两个村庄之间的距离就是它们坐标之差的绝对值。

    一些——但不一定是所有的村庄将修建邮局。邮局和该邮局所在的村庄处于同一位置。应当仔细选择邮局的位置,使得所有村庄到最近邮局的距离总和最短。

    你要编写一个程序,给出所有村庄的坐标和计划修建的邮局个数,计算所有村庄到最近邮局的距离总和的最小可能值。

    【输入格式】

    输入文件的第一行有2个正整数:村庄数V(1<=V<=300),邮局数P(1<=P<=30),P<=V。

    第二行有V个正整数,分别代表N个村庄的坐标。坐标的范围是[1,10000],坐标按递增顺序给出。

    【输出格式】

    输出一行一个正整数S,即所有村庄到最近邮局的距离总和的最小可能值。

    【样例输入】

    10 5

    1 2 3 6 7 9 11 22 44 50

    【样例输出】

    9

    【提示】

    对于30%的数据,1<=P<=N<=10.

    对于100%的数据,1<=P<=30,1<=N<=300,P<=N.

    /*与上面那个题如出一辙*/
    #define N 305
    #define P 35
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    int f[N][P],n,p;
    int x[N],dis[N][N];
    void input()
    {
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;++i)
          scanf("%d",&x[i]);
        for(int i=1;i<=n;++i)
          for(int j=i;j<=n;++j)
          {
              int mid=(i+j)>>1;
              for(int l=i;l<=j;++l)
              dis[i][j]+=abs(x[l]-x[mid]);
          }
        memset(f,99,sizeof(f));
        for(int i=1;i<=n;++i)
          f[i][1]=dis[1][i];
    }
    void dp()
    {
        for(int j=2;j<=p;++j)
          for(int i=j;i<=n;++i)
            for(int k=j-1;k<=i-1;++k) 
            f[i][j]=min(f[i][j],f[k][j-1]+dis[k+1][i]);
    }
    int main()
    {
    //    freopen("postoffice.in","r",stdin);
    //    freopen("postoffice.out","w",stdout);
        input();
        dp();
        printf("%d
    ",f[n][p]);
    //    fclose(stdin);fclose(stdout);
        return 0;
    }

    7.NOI 1808:公共子序列

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述
    我们称序列Z = < z1, z2, ..., zk >是序列X = < x1, x2, ..., xm >的子序列当且仅当存在 严格上升 的序列< i1, i2, ..., ik >,使得对j = 1, 2, ... ,k, 有xij = zj。比如Z = < a, b, f, c > 是X = < a, b, c, f, b, c >的子序列。

    现在给出两个序列X和Y,你的任务是找到X和Y的最大公共子序列,也就是说要找到一个最长的序列Z,使得Z既是X的子序列也是Y的子序列。
    输入
    输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200的字符串,表示两个序列。两个字符串之间由若干个空格隔开。
    输出
    对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度。
    样例输入
    abcfbc         abfcab
    programming    contest 
    abcd           mnp
    
    样例输出
    4
    2
    0
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 260
    #include<cstring>
    char a[N],b[N];
    int len1,len2;
    int f[N][N];
    int main()
    {
        while(scanf("%s%s",a+1,b+1)==2)
        {
            len1=strlen(a+1);
            len2=strlen(b+1);
            for(int i=1;i<=len1;++i)
              for(int j=1;j<=len2;++j)
              {
                  if(a[i]==b[j])
                    f[i][j]=f[i-1][j-1]+1;
                else f[i][j]=max(f[i-1][j],f[i][j-1]);
              }
            printf("%d
    ",f[len1][len2]);
            memset(a,0,sizeof(a));
            memset(b,0,sizeof(b));    
            memset(f,0,sizeof(f));
        }
        return 0;
    }

    8.

  • 相关阅读:
    创业者,你有梦想吗?
    中型企业能撑过现金危机
    共享经济与优步(Uber)如何获取监管支持?
    TJX:好买手养成记
    问得更少,获悉更多
    成功创新者该问的问题
    物联网革命的核心是“网”,而不是“物”
    成功领导力的10大关键
    人们抗拒组织变革的十大原因
    李彦宏:PC时代结束
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5598132.html
Copyright © 2020-2023  润新知