• 【wikioi】1025 选菜


    题目链接

    算法:01背包DP

    此题主要是预处理恶心。我提交了2次。。。第一次数组开小了。。。(体积要=V*10)

    注意:

    钱做为体积,美味价值作为价值

    注意,因为体积(钱)是小数点后1位,故数组下标无法表示体积(01背包),所以体积(钱)要扩大10倍作为01背包的体积
    还有因为有重复的,所以要去重再01

    代码:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    //钱做为体积,美味价值作为价值
    //注意,因为体积(钱)是小数点后1位,故数组下标无法表示体积(01背包)。所以要扩大10倍,输出答案再缩小10倍
    //还有因为有重复的,所以要去重再01
    const int MAXN = 105;
    int t[MAXN], n, k, V;			//t代表种类
    int v1[MAXN], w1[MAXN];			//v1代表价格(体积),w1代表美味价值(价值)(去重前)
    int v[MAXN], w[MAXN], nn = 0;	//v代表价格(体积),w代表美味价值(价值)
    int f[MAXN*10];
    bool m[MAXN];					//m[i]表示第i种是否被购买
    int ans = 0;
    
    int main()
    {
    	int i, j;
    	double temp;
    	int tem;
    	cin >> n >> k >> temp;
    	V=(int)(temp*10);
    	for(i = 1; i <= n; i++)	{cin >> temp; v1[i] = (int)(temp*10);}
    	for(i = 1; i <= n; i++)	cin >> w1[i];
    	for(i = 1; i <= n; i++)	cin >> t[i];
    	for(i = 1; i <= k; i++)
    	{
    		cin >> tem;
    		m[tem] = 1; //必买种类已经用过的标志
    		for(j = 1; j <= n; j++) //先处理必须买的
    			if(tem == t[i])
    			{
    				ans += w1[i];
    				V -= v1[i]; //必须买的后减小体积
    				break;
    			}
    	}
    	//题目说数据中不会出现小松带的钱不够买必买菜的情况,所以不用判断买完必要的后钱不够的情况
    	if(V == 0) {cout << ans << endl;return 0;}
    	for(i = 1; i <= n; i++)
    		if(!m[t[i]]) //这种种类没有访问过
    			w[++nn]=w1[i], v[nn]=v1[i], m[t[i]]=1;
    	//01背包
    	for(i = 1; i <= nn; i++)
    		for(j = V; j >= v[i]; j--)
    			f[j] = max(f[j], f[j-v[i]]+w[i]);
    	cout << ans+f[V] << endl;
    	return 0;
    }
  • 相关阅读:
    POJ2253Frogger
    POJ3982The Fibonacci sequence
    POJ3259Wormholes
    POJ1062Expensive dowry
    POJ1860Currency Exchange
    POJ1789Truck History .
    POJ2602Superlong sums
    POJ1125Stockbroker Grapevine
    POJ2485Highways
    POJ2240Arbitrage
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3521800.html
Copyright © 2020-2023  润新知