zoukankan      html  css  js  c++  java
  • 动态规划

    1.对抗赛

    【问题描述】

    程序设计对抗赛设有N(0<N<=50)个价值互不相同的奖品,每个奖品的价值分别为S1,S2,S3,...,Sn(均为不超过100的正整数)。现将他们分给甲乙两队,为了使得甲乙两队得到相同价值的奖品,必须将这N个奖品分成价值相同的两组。

    编成要求:对给定N及N个奖品的价值,求出将这N个奖品分成价值相同的两组,共有多少种分发?

    例如N=5,S1,S2,S3...,Sn分别为1,3,5,8,9

    则可分为{1,3,9}与{5,8},仅有一种分法;

    例如N=7,S1,S2,S3...,Sn分别为1,2,3,4,5,6,7

    则可分为:

    {1,6,7}与{2,3,4,5}

    {2,5,7}与{1,3,4,5}

    {3,4,7}与{1,2,5,6}

    {1,2,4,7}与{3,5,6}

    有4种分法。

    【输入格式】

    N

    S1,S2,S3,...,Sn.

    【输出格式】

    共有多少种分法,无解则输出0;

    【输入样例】

    7

    1 2 3 4 5 6 7

    【输出样例】

    4

    /*求方案总数的01背包,就是把max或者min改为求sum即可,注意f[0]=1--初始化*/
    #include<iostream>
    using namespace std;
    #include<cstdio>
    int f[5001],n;
    int val[51];
    int main()
    {
        int sum=0;
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&val[i]);
            sum+=val[i];
        }
        sum/=2;
        f[0]=1;
        for(int i=1;i<=n;++i)
          for(int j=sum;j>=val[i];--j)
          f[j]+=f[j-val[i]];
        cout<<f[sum]/2<<endl;/*注意一定要/2输出,因为方案包括了分组的另一半*/
        return 0;
    }
    

    2.演讲安排

    演讲大厅安排:

    有一个演讲大厅需要我们管理,演讲者们事先定好了需要演讲的起始时间和中止时间。我们想让演讲大厅得到最大可能的使用。我们要接受一些预定而拒绝其他的预定,目标是使演讲者使用大厅的时间最长。假设在某一时刻一个演讲结束,另一个演讲就可以立即开始。

    问题求解:

    1、  从文本文件HALL.IN中读入演讲者的申请。

    2、  计算演讲大厅最大可能的使用时间。

    3、  将结果写入文件HALL.OUT。

    输入文件(HALL.IN):

    输入文件HALL.IN第一行为一个整数N,N≤5000,表示申请的数目。

    以下n行每行包含两个整数p,k,1 ≤ p < k ≤ 10000,表示这个申请的起始时间和中止时间。

    输出文件(HALL.OUT):

    输出文件HALL.OUT包含一个整数,表示大厅最大可能的使用时间。

    输入输出示例:

    HALL.IN
    12
    1 2
    3 5
    0 4
    6 8
    7 13
    4 6
    9 10
    9 12
    11 14
    15 19
    14 16
    18 20

    HALL.OUT

    16

     注意:可以按照开始排序,也可以按照尾排序,结果是相同的

    #include<iostream>
    using namespace std;
    #include<cstdio>
    #include<algorithm>
    struct Yj{
        int p,k;
        bool operator<(const Yj &x)const {
        return k<x.k;
        }/*重载运算符的使用,左边的结构体的k小于右边的结构体的k,左边是指这个Yj不加x.,x.k是指后一个*/
    }; 
    Yj yj[5010];
    int n;
    long long int dp[5010];
    void input()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        scanf("%d%d",&yj[i].p,&yj[i].k);
        sort(yj+1,yj+n+1);
    }
    void DP()
    {
        /*注意:不能初始化f[1]因为这可能不是最优解,要通过循环来找*/
        for(int i=1;i<=n;++i)
          for(int j=0;j<=i-1;++j)
          if(yj[i].p>=yj[j].k)/*>=是因为 假设在某一时刻一个演讲结束,另一个演讲就可以立即开始。*/
          dp[i]=max(dp[i],dp[j]+yj[i].k-yj[i].p);
    }
    int main()
    {
        freopen("hall.in","r",stdin);
    //    freopen("hall.out","w",stdout);
        input();
        DP();
        cout<<dp[n]<<endl;
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    
  • 相关阅读:
    CSUFT 1002 Robot Navigation
    CSUFT 1003 All Your Base
    Uva 1599 最佳路径
    Uva 10129 单词
    欧拉回路
    Uva 10305 给任务排序
    uva 816 Abbott的复仇
    Uva 1103 古代象形文字
    Uva 10118 免费糖果
    Uva 725 除法
  • 原文地址:https://www.cnblogs.com/yskn/p/9637100.html
Copyright © 2011-2022 走看看