• Week11 作业 F


    题目描述:

    东东开车出去泡妞(在梦中),车内提供了 n 张CD唱片,已知东东开车的时间是 n 分钟,他该如何去选择唱片去消磨这无聊的时间呢

    假设:

    • CD数量不超过20张
    • 没有一张CD唱片超过 N 分钟
    • 每张唱片只能听一次
    • 唱片的播放长度为整数
    • N 也是整数

    我们需要找到最能消磨时间的唱片数量,并按使用顺序输出答案(必须是听完唱片,不能有唱片没听完却到了下车时间的情况发生)

    本题是 Special Judge

    思路:

    • 题目很简单,就是01背包,但是要输出路径,但是这里的路径不要求是字典序最小
    • 可以直接逆着递推过程去打印方案,没什么问题
    • 而且可以发现,下述代码打印的方案不一定是字典序最小的,因为是逆向打印
    • 研究了很长时间如何字典序打印路径和为什么逆向打印是不可行的,感觉还是很难理解,我感觉应该再熟悉一下DP然后再来解决打印最小字典序这个问题

    总结:

    可以按照递推或搜索的过程来逆向打印路径

    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int MAXN=1e4+5;
    int f[25][MAXN];
    int w[25]; //w[i]==v[i]
    //输出到达 只考虑前i个物品容量为j时最大值 的路径 
    void print(int i,int j)	
    {
    	if(i<=0) return;
    	if(f[i][j]==f[i-1][j])	//第i个物品没选
    	{
    		print(i-1,j);	
    	}
    	else if( j-w[i]>=0 && f[i][j]==f[i-1][j-w[i]]+w[i]) //第i个物品选了
    	{
    		print(i-1,j-w[i]);
    		cout<<w[i]<<' ';
    	} 
    }
    int main()
    {
    	int N,M;
    	while( scanf("%d %d",&N,&M)==2 )
    	{
    		memset(f,0,sizeof(f));
    		
    		for(int i=1;i<=M;i++)
    			scanf("%d",w+i);
    		for(int i=1;i<=M;i++)
    			for(int j=0;j<=N;j++)
    			{
    				f[i][j]=f[i-1][j];
    				if( j>=w[i] )
    					f[i][j]=max(f[i][j],f[i-1][j-w[i]]+w[i]);							
    			}
    		print(M,N);
    		cout<<"sum:"<<f[M][N]<<endl;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    使用VS2015将解决方案同步更新到Github上
    SQL Server循环
    OSPF
    OPSF
    OSPF
    pandas更换index,column名称
    pandas的时间戳
    pandas选择单元格,选择行列
    BGP
    BGP
  • 原文地址:https://www.cnblogs.com/qingoba/p/12938419.html
Copyright © 2020-2023  润新知