• P1108 低价购买 (动态规划)


    题目链接


    Solution

    似乎就是个很简单的最长不上升子序列输出方案.
    但是有一个很艹蛋的条件: 不同方案选择价格必须不同.
    且其股票价格不保证不相同.

    (f[i]) 代表以第 (i) 天结尾的不上升子序列的长度.

    其实我们可以推出一个条件 : 相同的两个股票价格同时出现,后者的方案里面一定包括前者的.
    这也是我们按平常做法多出来的方案数.
    所以我们可以直接在 DP 的时候记录一个 (g[i][j]) 代表在 (i) 时由最后一个价值为 (j) 的已经累加的次数.
    然后每次加上的便是 (g[v][j]-g[i][j]). 其中 (v) 为可以转移到 (i) 最优方案的节点.

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5008;
    int w[maxn],n;
    int f[maxn];
    map<int,int>g[maxn];
    map<int,int>v;
    int ans,ans_num;
    int main()
    {
    	scanf("%d",&n); w[0]=0x3f3f3f3f;
    	for(int i=1;i<=n;i++)
    	scanf("%d",&w[i]);
    	g[0][w[0]]=1; f[0]=0;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<i;j++)
    		if(w[i]<w[j])
    		  	if(f[j]+1>f[i])
    		    	f[i]=f[j]+1;
    		
    		for(int j=0;j<i;j++)
    		if(w[i]<w[j])
    			if(f[j]+1==f[i])
    			{
    				g[i][w[i]]+=(g[j][w[j]]-g[i][w[j]]);
    				g[i][w[j]]=g[j][w[j]];
    			}		
    	}
    	for(int i=1;i<=n;i++)
    		if(f[i]>ans)ans=f[i];
    	for(int i=1;i<=n;i++)
    		if(f[i]==ans)
    		{
    			ans_num+=g[i][w[i]]-v[w[i]];
    			v[w[i]]=g[i][w[i]];
    		}
    	cout<<ans<<' '<<ans_num;
    	return 0;
    }
    
  • 相关阅读:
    Redundant Connection
    Recover Binary Search Tree
    Min Stack
    *Flatten Binary Tree to Linked List
    Copy List with Random Pointer
    Binary Tree Maximum Path Sum
    Arithmetic Slices
    Integer to English Words
    Unique Email Addresses
    Mycat(水平拆分--分表 全局序列)
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9673062.html
Copyright © 2020-2023  润新知