zoukankan      html  css  js  c++  java
  • 4.15 每周作业 —— 简单DP

    免费馅饼

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 102   Accepted Submission(s) : 35

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。但由于小径两侧都不能站人,所以他只能在小径上接。由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身手敏捷的高手,但在现实中运动神经特别迟钝,每秒种只有在移动不超过一米的范围内接住坠落的馅饼。现在给这条小径如图标上坐标:

    为了使问题简化,假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。开始时gameboy站在5这个位置,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。问gameboy最多可能接到多少个馅饼?(假设他的背包可以容纳无穷多个馅饼)

    Input

    输入数据有多组。每组数据的第一行为以正整数n(0<n<100000),表示有n个馅饼掉在这条小径上。在结下来的n行中,每行有两个整数x,T(0<T<100000),表示在第T秒有一个馅饼掉在x点上。同一秒钟在同一点上可能掉下多个馅饼。n=0时输入结束。

    Output

    每一组输入数据对应一行输出。输出一个整数m,表示gameboy最多可能接到m个馅饼。
    提示:本题的输入数据量比较大,建议用scanf读入,用cin可能会超时。

    Sample Input

    6
    5 1
    4 1
    6 1
    7 2
    7 2
    8 3
    0
    

    Sample Output

    4

    思路: 简单DP,按照DP的思考步骤。

       一.找到最优子问题
         那么我们的问题就是 “左 中 右”的选择

       二.找到决策,也就是会影响到结果的因素
         那么这个问题会影响到结果的就是 时间和地点

       三.提出状态
         由第二点可以知道,影响到结果的有两个因素,所以状态应该是二维的
         DP[i][j]==在 i秒 的时候 在 j点 的馅饼数

       四.提出状态转移方程
         考虑到边界问题,如果我们在第 0 点 或者 第 10 点,那我们的选择就只有 “在原地”或者 “旁边的一个”,这样就只有两个选择,所以需要特判一下

             if(j<=0){
                        j=0;
                        dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+cake[i][j];
                    }
                    else if(j==10){
                        dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+cake[i][j];
                    }
                    else{
                        dp[i][j]=max_judge(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+cake[i][j];//比较一下第i秒的j号位置,是上一秒的j的左边,还是上一秒的j的右边,还是上一秒的j最多
                    }

        其实我们可以看到,我们每次要考虑到的只有上一秒的情况,所以其实可以用滚动数组来节省空间,不过我懒得写了,不会的话参考01背包的滚动数组情况。

        下面给出麻烦代码

        

    //#pragma comment(linker,"/STACK:1024000000,1024000000")
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<vector>
    #include<set>
    #include<map>
    using namespace std;
    
    int n;
    int T,x;
    int loc;
    int Max;
    int sum_time;
    int cake[100005][15];
    int dp[100005][15];
    
    int max_judge(int a,int b,int c)
    {
        int ans;
        ans=a>b?a:b;
        ans=ans>c?ans:c;
        return ans;
    }
    
    int main()
    {
        while(cin>>n && n)
        {
            loc=5;
            Max=0;
            sum_time=0;
            memset(dp,0,sizeof(dp));
            memset(cake,0,sizeof(cake));
            for(int i=1;i<=n;i++){
                scanf("%d%d",&x,&T);
                sum_time=max(T,sum_time);
                cake[T][x]++;
            }
            
            for(int i=1;i<=sum_time;i++){
                for(int j=loc-i;j<=10 && j<=loc+i;j++){
                    if(j<=0){
                        j=0;
                        dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+cake[i][j];
                    }
                    else if(j==10){
                        dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+cake[i][j];
                    }
                    else{
                        dp[i][j]=max_judge(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+cake[i][j];
                    }
                }
                
            }
            for(int i=0;i<=10;i++){
                Max=max(dp[sum_time][i],Max);
            }
            cout<<Max<<endl;
        }
        return 0;
    }

    搬寝室

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 63   Accepted Submission(s) : 23

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    搬寝室是很累的,xhd深有体会.时间追述2006年7月9号,那天xhd迫于无奈要从27号楼搬到3号楼,因为10号要封楼了.看着寝室里的n件物品,xhd开始发呆,因为n是一个小于2000的整数,实在是太多了,于是xhd决定随便搬2*k件过去就行了.但还是会很累,因为2*k也不小是一个不大于n的整数.幸运的是xhd根据多年的搬东西的经验发现每搬一次的疲劳度是和左右手的物品的重量差的平方成正比(这里补充一句,xhd每次搬两件东西,左手一件右手一件).例如xhd左手拿重量为3的物品,右手拿重量为6的物品,则他搬完这次的疲劳度为(6-3)^2 = 9.现在可怜的xhd希望知道搬完这2*k件物品后的最佳状态是怎样的(也就是最低的疲劳度),请告诉他吧.

    Input

    每组输入数据有两行,第一行有两个数n,k(2<=2*k<=n<2000).第二行有n个整数分别表示n件物品的重量(重量是一个小于2^15的正整数).

    Output

    对应每组输入数据,输出数据只有一个表示他的最少的疲劳度,每个一行.

    Sample Input

    2 1
    1 3

    Sample Output

    4

    Author

    xhd

    Source

    ACM暑期集训队练习赛(二)

    思路:这题一开始感觉是简单排序,然后就WA了,后面想想不行   比如      1    99    100  这样的数据,简单排序选择的话 就会选择1 和99 ,但实际上是 99 和 100.

       还是得靠DP来解决。

       正式开始

       首先,我们先sort排序下。 这样,我们知道,两个数的差最小的话,肯定是排序后的左边一个和右边一个,这样我们的问题就变成了选左边或者右边。

       下面按照DP的简单思路:

       一.找出最小子问题

        我们的问题就是选出相差值最小的一对,那么我们面对的问题就 我们要拿的这一对中 包不包含现在面对的这个 东西

       二.找到决策,也就是影响到结果的因素

        那么我们可以知道,影响到问题的决策 也就是 物品 和 对数    

       三.提出状态

        由二我们可以知道影响到问题的决策有两个 也就是 状态也就是 二维的

        DP[i][j]==在面对第 i 个 物品时,拿了 j 对 物品的疲劳值

       四.提出转移方程  

          dp[i][j] = Min_(dp[i - 2][j - 1] +sum(wei[i],wei[i-1]),dp[i - 1][j]);
        
          //比较下 是拿 这一个加前一个 这一对 加上前面的对数 的疲劳值 和 不拿这一个 的 对数 的疲劳值

        下面给出AC程序:

        可能还是有人比较模糊,那就再解释下。

        我们从最小的状态开始,也就是

        比如只有  a  b两件,那么我们只能拿这两个 

        但是如果有 a b c 三件,首先我们知道  c-a 肯定是大于 c-b的,所以不需要考虑

        所以我们要考虑的是要不要拿c,如果拿c的话,那么我们肯定是要拿b的,如果不拿c的话,那么我们就是拿a 和 b了

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    #define M 2005
    typedef  int ll;
    
    ll n, k;
    ll limit_i;
    ll limit_k;
    ll wei[M];
    ll dp[M][M];
    
    void init()
    {
        memset(dp, 0x3f3f3f3f, sizeof(dp));
        for (int i = 0; i <= n; i++) {
            dp[i][0] = dp[0][i] = 0;
        }
    }
    
    ll Min_(ll a, ll b)
    {
        return a < b ? a : b;
    }
    
    ll sum(ll a, ll b)
    {
        return (a - b)*(a - b);
    }
    
    int main()
    {
        while (cin>>n>>k)
        {
            init();
            for (int i = 1; i <= n; i++) {
                scanf("%d", &wei[i]);
            }
            sort(wei + 1, wei + n + 1);
    
            for (int i = 2; i <= n; i++) {
                limit_i = (i >>1);
                for (int j = 1; j <= limit_i && j <= k; j++) {
                    dp[i][j] = Min_(dp[i - 2][j - 1] +sum(wei[i],wei[i-1]),dp[i - 1][j]);
                }
            }
            cout << dp[n][k] << endl;
        }
        return 0;
    }

    Humble Numbers

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 12   Accepted Submission(s) : 9

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    A number whose only prime factors are 2,3,5 or 7 is called a humble number. The sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, ... shows the first 20 humble numbers. 

    Write a program to find and print the nth element in this sequence

    Input

    The input consists of one or more test cases. Each test case consists of one integer n with 1 <= n <= 5842. Input is terminated by a value of zero (0) for n.

    Output

    For each test case, print one line saying "The nth humble number is number.". Depending on the value of n, the correct suffix "st", "nd", "rd", or "th" for the ordinal number nth has to be used like it is shown in the sample output.

    Sample Input

    1
    2
    3
    4
    11
    12
    13
    21
    22
    23
    100
    1000
    5842
    0
    

    Sample Output

    The 1st humble number is 1.
    The 2nd humble number is 2.
    The 3rd humble number is 3.
    The 4th humble number is 4.
    The 11th humble number is 12.
    The 12th humble number is 14.
    The 13th humble number is 15.
    The 21st humble number is 28.
    The 22nd humble number is 30.
    The 23rd humble number is 32.
    The 100th humble number is 450.
    The 1000th humble number is 385875.
    The 5842nd humble number is 2000000000.
    

    Source

    University of Ulm Local Contest 1996
     
     
    题意:英语题先说下题意,也就是能整除 2 3 5 7任意一个数的就能算入排列,不过要按大小顺序排列
     
    思路:我的思路比较简单,按顺序,每一个数都乘以 2 3 5 7,然后把积放入set里面自动排序,最后再把set转化成数组,不过耗时较大。
       这题有个大坑点,也就是首先 我们可以 看到 格式  尾数为 1 的是用 st,2的使用 nd ,3的是用 rd,但是偏偏 以 11  12  13 结尾的都是用 th
     
    下面给出AC代码:
      
    //#pragma comment(linker,"/STACK:1024000000,1024000000")
    #include<iostream>
    #include<algorithm>
    #include<iterator>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<list>
    #include<set>
    #include<deque>
    #include<utility>
    #include<ctime>
    using namespace std;
    
    typedef long long ll;
    
    ll t;
    ll temp;
    ll n[] = { 2,3,5,7 };
    ll ans[6000];
    set<ll>num;
    string str[10];
    
    void init()
    {
        num.insert(1), num.insert(0);
        register set<ll>::iterator iter = num.begin();
        for (int i = 1; i <= 4900; i++) {
            iter++;
            for (int j = 0; j < 4; j++) {
                temp = (*iter)*n[j];
                num.insert(temp);
            }
        }
        iter = num.begin();
        for (int i = 0; i <= 5842; i++) {
            ans[i] = *iter;
            iter++;
        }
        str[0] = "th", str[1] = "st", str[2] = "nd", str[3] = "rd";
        for (int i = 4; i <= 9; i++) {
            str[i] = "th";
        }
    }
    
    int main()
    {
        init();
        while (cin>>t && t)
        {
            cout << "The " << t;
            if (t%100 == 11 || t % 100 == 12 || t % 100 == 13) {
                cout << str[0];
            }
            else {
                cout << str[t % 10];
            }
            cout << " humble number is " << ans[t] << '.' << endl;
        }
        return 0;
    }

    Super Jumping! Jumping! Jumping!

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 44   Accepted Submission(s) : 27

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. Maybe you are a good boy, and know little about this game, so I introduce it to you now.



    The game can be played by two or more than two players. It consists of a chessboard(棋盘)and some chessmen(棋子), and all chessmen are marked by a positive integer or “start” or “end”. The player starts from start-point and must jumps into end-point finally. In the course of jumping, the player will visit the chessmen in the path, but everyone must jumps from one chessman to another absolutely bigger (you can assume start-point is a minimum and end-point is a maximum.). And all players cannot go backwards. One jumping can go from a chessman to next, also can go across many chessmen, and even you can straightly get to end-point from start-point. Of course you get zero point in this situation. A player is a winner if and only if he can get a bigger score according to his jumping solution. Note that your score comes from the sum of value on the chessmen in you jumping path.
    Your task is to output the maximum value according to the given chessmen list.

    Input

    Input contains multiple test cases. Each test case is described in a line as follow:
    N value_1 value_2 …value_N 
    It is guarantied that N is not more than 1000 and all value_i are in the range of 32-int.
    A test case starting with 0 terminates the input and this test case is not to be processed.

    Output

    For each case, print the maximum according to rules, and one line one case.

    Sample Input

    3 1 3 2
    4 1 2 3 4
    4 3 3 2 1
    0
    

    Sample Output

    4
    10
    3
    

    Author

    lcy
     
     
    题意: 英文题先说下题意,也就是从起点开始,你可以跳到任何一个比现在大的数,当然也可以一步到结尾,现在问题找到一条 跳到的数和 为最大的一条路
     
    思路:很明显就是最长上升子序列,但是需要记录的是值,而不是长度。依然是简单DP问题
     
     
       一.找到最小子问题
        首先能不能跳,其次要不要跳到这个数。
        那么假如我们只有  起点   a  终点 ,那么肯定是 起点--a--终点
        假如我们有 起点 a b 终点,那么如果我们以 a为结尾的话,那么就是  起点--a--终点
        如果我们以 b 为结尾的话,那么就要判断  是从 起点--b   还是  起点--a--b 好
       二.决策,也就是影响结果的因素
        我们可以分析,影响到结果的只有数的大小
     
       三.提出状态
        由二可以知道,影响到结果的只有 数的大小,那么状态应该是一维的
     
       四.提出状态转移方程    
                    if (num[j] < num[i]) {
                        dp[i] = max(dp[i], dp[j] + num[i]);
                    }//比较一下,如果以i点为结尾的话,会不会更大

       下面给出AC方程:

        

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<list>
    #include<deque>
    #include<utility>
    using namespace std;
    
    #define M 1005
    
    int n;
    int ans;
    int dp[M];
    int num[M];
    
    void init()
    {
        ans = 0;
        for (int i = 1; i <= n; i++) {
            dp[i] = num[i];
        }
    }
    
    int main()
    {
        while (cin>>n && n)
        {
            for (int i = 1; i <= n; i++) {
                cin >> num[i];
            }
            init();
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= i; j++) {
                    if (num[j] < num[i]) {
                        dp[i] = max(dp[i], dp[j] + num[i]);
                    }
                }
                ans = max(ans, dp[i]);
            }
            cout << ans << endl;
        }
    
        return 0;
    }

    龟兔赛跑

    Time Limit : 1000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 18   Accepted Submission(s) : 8

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    据说在很久很久以前,可怜的兔子经历了人生中最大的打击——赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州下沙某农业园卧薪尝胆潜心修炼,终于练成了绝技,能够毫不休息得以恒定的速度(VR m/s)一直跑。兔子一直想找机会好好得教训一下乌龟,以雪前耻。
    最近正值HDU举办50周年校庆,社会各大名流齐聚下沙,兔子也趁此机会向乌龟发起挑战。虽然乌龟深知获胜希望不大,不过迫于舆论压力,只能接受挑战。
    比赛是设在一条笔直的道路上,长度为L米,规则很简单,谁先到达终点谁就算获胜。
    无奈乌龟自从上次获胜以后,成了名龟,被一些八卦杂志称为“动物界的刘翔”,广告不断,手头也有了不少积蓄。为了能够再赢兔子,乌龟不惜花下血本买了最先进的武器——“"小飞鸽"牌电动车。这辆车在有电的情况下能够以VT1 m/s的速度“飞驰”,可惜电池容量有限,每次充满电最多只能行驶C米的距离,以后就只能用脚来蹬了,乌龟用脚蹬时的速度为VT2 m/s。更过分的是,乌龟竟然在跑道上修建了很多很多(N个)的供电站,供自己给电动车充电。其中,每次充电需要花费T秒钟的时间。当然,乌龟经过一个充电站的时候可以选择去或不去充电。
    比赛马上开始了,兔子和带着充满电的电动车的乌龟并列站在起跑线上。你的任务就是写个程序,判断乌龟用最佳的方案进军时,能不能赢了一直以恒定速度奔跑的兔子。

    Input

    本题目包含多组测试,请处理到文件结束。每个测试包括四行:
    第一行是一个整数L代表跑道的总长度
    第二行包含三个整数N,C,T,分别表示充电站的个数,电动车冲满电以后能行驶的距离以及每次充电所需要的时间
    第三行也是三个整数VR,VT1,VT2,分别表示兔子跑步的速度,乌龟开电动车的速度,乌龟脚蹬电动车的速度
    第四行包含了N(N<=100)个整数p1,p2...pn,分别表示各个充电站离跑道起点的距离,其中0<p1<p2<...<pn<L
    其中每个数都在32位整型范围之内。

    Output

    当乌龟有可能赢的时候输出一行 “What a pity rabbit!"。否则输出一行"Good job,rabbit!";
    题目数据保证不会出现乌龟和兔子同时到达的情况。

    Sample Input

    100
    3 20 5
    5 8 2
    10 40 60
    100
    3 60 5
    5 8 2
    10 40 60

    Sample Output

    Good job,rabbit!
    What a pity rabbit!

    Author

    linle

    Source

    校庆杯Warm Up
     
    思路:很明显这是一个最短子序列的问题,这样的话我们就先把 起点 和终点 也加入 序列中,把起点和终点也当成 ”站“,这样就是一个简单的DP了
       
       DP的思路:
       一.最小子问题
        我们面对的问题就是要不要在这个站充电
        比如说   起点   a  终点
        我们就可以比较下,是 起点--a--终点 快,还是 起点--终点 快。
       
       二.决策,也就是影响问题的因素
        我们把它当成一个最短子序列的问题,这样的话影响到结果的就只有 ”站“,状态也就是一维
        
       三.提出状态
        DP[i]==到达i站时花费的时间
       
       四.转移方程
        
      dp[i] = min(dp[i], dp[j] + sum(i, j));//sum计算的是从j到i花费的时间

        下面是AC方程:

        

    //#pragma comment(linker,"/STACK:1024000000,1024000000")
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<list>
    #include<deque>
    #include<utility>
    using namespace std;
    
    #define M 105
    #define inf 0x3f3f3f3f
    typedef double i_d;
    
    int L;
    i_d r_time;
    int st, ed;
    i_d N, C, T;
    i_d VR, VT1, VT2;
    i_d dp[105];
    int num[105];
    
    void init()
    {
        r_time = L / VR;
        ed = 0, st = N + 1;
        num[ed] = 0, num[st] = L;
        for (int i = 1; i <= st; i++) {
            dp[i] = inf;
        }
        dp[0] = 0;
    }
    
    void get_data()
    {
        cin >> N >> C >> T;
        cin >> VR >> VT1 >> VT2;
        for (int i = 1; i <= N; i++) {
            cin >> num[i];
        }
    }
    
    i_d sum(int a, int b)
    {
        i_d dis, time;
        dis = num[a] - num[b];
        if (dis <= C) {
            time=dis / VT1;
        }
        else {
            time = C / VT1 + (dis - C) / VT2;
        }
        return b == 0 ? time : time + T;//记住如果j站为0的话那么就是起点,起点不需要充电,也就不需要花费T时间
    }
    
    int main()
    {
        while (cin>>L)
        {
            get_data();
            init();
            for (int i = 1; i <= st; i++) {
                for (int j = 0; j < i; j++) {
                    dp[i] = min(dp[i], dp[j] + sum(i, j));
                }
            }
            if (r_time < dp[st]) {
                cout << "Good job,rabbit!" << endl;
            }
            else {
                cout << "What a pity rabbit!" << endl;
            }
        }
        return 0;
    }

      

    FatMouse's Speed

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 12   Accepted Submission(s) : 5
    Special Judge

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take the data on a collection of mice and put as large a subset of this data as possible into a sequence so that the weights are increasing, but the speeds are decreasing.

    Input

    Input contains data for a bunch of mice, one mouse per line, terminated by end of file.

    The data for a particular mouse will consist of a pair of integers: the first representing its size in grams and the second representing its speed in centimeters per second. Both integers are between 1 and 10000. The data in each test case will contain information for at most 1000 mice.

    Two mice may have the same weight, the same speed, or even the same weight and speed. 

    Output

    Your program should output a sequence of lines of data; the first line should contain a number n; the remaining n lines should each contain a single positive integer (each one representing a mouse). If these n integers are m[1], m[2],..., m[n] then it must be the case that 

    W[m[1]] < W[m[2]] < ... < W[m[n]]

    and 

    S[m[1]] > S[m[2]] > ... > S[m[n]]

    In order for the answer to be correct, n should be as large as possible.
    All inequalities are strict: weights must be strictly increasing, and speeds must be strictly decreasing. There may be many correct outputs for a given input, your program only needs to find one. 

    Sample Input

    6008 1300
    6000 2100
    500 2000
    1000 4000
    1100 3000
    6000 2000
    8000 1400
    6000 1200
    2000 1900
    

    Sample Output

    4
    4
    5
    9
    7
    

    Source

    Zhejiang University Training Contest 2001
     
    题意:给出一堆老鼠的体重和速度的数据直到文件结束,然后要你找出这些老鼠,哪些符合”随着体重的增加而速度变慢”
     
    思路:我们可以先用一个结构体储存数据,然后把体重按照从小到大排序,这样我们就可以直接对它们的速度进行分析,也就是找出一个最长下降子序列
       但是记得,结果还要输出它们的号码,也就是没排序之前的号码,所以记得先把号码存入结构体中
       然后它又要按照从小到大排序,所以我们就用一个递归来输出
     
    下面给出AC方程
    //#pragma comment(linker,"/STACK:1024000000,1024000000")
    #include<iostream>
    #include<algorithm>
    #include<iterator>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<list>
    #include<set>
    #include<queue>
    #include<deque>
    #include<utility>
    #include<ctime>
    using namespace std;
    
    #define M 1005
    #define inf 0x3f3f3f3f
    
    struct Data
    {
        int id;
        int wei;
        int speed;
        bool operator<(Data &x){
            return wei < x.wei;
        }
    }Mouse[M];
    int dp[M];
    int ans[M];
    int n, len, tail;
    int id, wei, speed;
    
    void get_data()
    {
        id = 1;
        while (cin>>wei>>speed)
        {
            //if (wei == 0) { break; }
            Mouse[id].id = id;
            Mouse[id].wei = wei;
            Mouse[id++].speed = speed;
        }
        Mouse[0].wei = inf, Mouse[0].speed = -inf;
        n = id - 1;
    }
    
    void dfs(int T)
    {
        if (!T) {
            return;
        }
        dfs(ans[T]);
        cout << Mouse[T].id << endl;
    }
    
    int main()
    {
        get_data();    
        sort(Mouse + 1, Mouse + n + 1);
        for (int i = 1; i <= n; i++) {
            dp[i] = 1;
            for (int j = 1; j < i; j++) {
                if (Mouse[i].wei > Mouse[j].wei && Mouse[i].speed < Mouse[j].speed && dp[i] < dp[j] + 1) {
                    dp[i] = dp[j] + 1;
                    ans[i] = j;
                }
            }
            if (len < dp[i]) {
                len = dp[i];
                tail = i;
            }
        }
        cout << len << endl;
        dfs(tail);
        return 0;
    }

    Common Subsequence

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 12   Accepted Submission(s) : 6

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a strictly increasing sequence <i1, i2, ..., ik> of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = <a, b, f, c> is a subsequence of X = <a, b, c, f, b, c> with index sequence <1, 2, 4, 6>. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y. 
    The program input is from a text file. Each data set in the file contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct. For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line. 

    Sample Input

    abcfbc abfcab
    programming contest 
    abcd mnp
    

    Sample Output

    4
    2
    0
    

    Source

    Southeastern Europe 2003
     
    题意:英文题先给题意。给出两个字符串,要你找出两个字符串最长的公共子序列
     
    思路:很明白的告诉你要找出最长公共子序列
       
    下面给出AC方程:
        
    //#pragma comment(linker,"/STACK:1024000000,1024000000")
    #include<iostream>
    #include<algorithm>
    #include<iterator>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<list>
    #include<set>
    #include<deque>
    #include<utility>
    #include<ctime>
    using namespace std;
    
    #define M 1005
    
    int a_len;
    int b_len;
    int dp[M][M];
    char a[M], b[M];
    
    void init()
    {
        a_len = strlen(a + 1), b_len = strlen(b + 1);
        for (int i = 0; i <= a_len; i++) {
            for (int j = 0; j <= b_len; j++) {
                dp[i][j] = 0;
            }
        }
    }
    
    int main()
    {
        while (scanf("%s%s",a+1,b+1)!=EOF)
        {
            init();
            for (int i = 1; i <= a_len; i++) {
                for (int j = 1; j <= b_len; j++) {
                    if (a[i] == b[j]) {
                        dp[i][j] = dp[i - 1][j - 1] + 1;
                    }
                    else {
                        dp[i][j] = max(dp[i - 1][j], dp[i][j-1]);
                    }
                }
            }
            cout << dp[a_len][b_len] << endl;
        }
        return 0;
    }
     
  • 相关阅读:
    让你平步青云的10个谈话技巧
    瑞士心理学家和精神分析医师――荣格
    市场倍增理论
    淘宝网格,淘宝富人群
    波波的个人简历
    磁盘修复工具
    9种没结果的爱(未婚者必读)!!!
    网络投机市场
    网页数据抽取的方法介绍
    C#扩展方法试用
  • 原文地址:https://www.cnblogs.com/caibingxu/p/10712670.html
Copyright © 2011-2022 走看看