CCF- CSP 202209-2 何以包邮? 两种方法 dfs+离散化 满分题解

CCF- CSP 202209-2 何以包邮? 两种方法 dfs+离散化 满分题解

题目链接:202209-2 何以包邮?

思路1(离散化):

  • n最大为30,a最大为104,所以最大价格为3e5
  • 将所有组合的价格映射到f上,从x开始向大进行查找,直到找到第一个大于等于x的价格(存在此组合)
  • 技巧在于求各种组合的价格,也是采用离散化的思想,将每一个价格和组合映射到f上,每次从M开始遍历整个f,找到加入当前price后,此price和之前的组合形成的新组合所对应的值

代码如下:

#include
using namespace std;
const int N = 50, M = 3e5 + 10;//M的范围得大
int n,x;
int price[N];//价格
int f[M];//存储离散化后的点
int main()
{
    cin>>n>>x;
    for(int i=1;i<=n;i++)
    {
        cin>>price[i];
    }
    
    //得到各种组合后的价格
    f[0]=1;//初始化
    for(int i=1;i<=n;i++)
    {
        for(int j=M;j>=price[i];j--)
        {
            if(f[j-price[i]])
            {
                f[j]=1;
            }
        }
    }
    
    int out = x;//起始位置
    while(1)
    {
        if(f[out])break;//找到第一个大于等于x的价格
        else
        {
            out++;
        }
    }
    cout<<out<<endl;
    return 0;
}

思路2(dfs不剪枝70分):

  • 对于每本书,都有选和不选两种方案,可以对应一棵完全二叉树
  • 遍历所有书的两种方案,找到最小值,采用dfs算法

70分代码如下:

#include
#include
using namespace std;
const int N = 50;
int n,x;
int price[N];
int ans = 1e9;
void dfs(int k,int sum)
{
    
    if(sum>=x)
    {
        ans = min(sum,ans);//更新最小值
    }
    if(k>n)
    {
        return;
    }
    dfs(k+1, sum+price[k]);//选择这本书
    dfs(k+1,sum);//不选择这本书
}
int main()
{
    cin>>n>>x;
    for(int i=1;i<=n;i++)
    {
        cin>>price[i];
    }
    dfs(1,0);//从第一本书开始
    cout<<ans<<endl;
}

思路三(dfs+剪枝100分):

  • 在思路二的基础上,对二叉树进行剪枝
  • 剪枝思路:当前节点sum加上剩余节点的所有值之和已经小于x了,进行剪枝
  • 求剩余节点的所有值,可以采用前缀和的思想

代码如下:

#include
#include
using namespace std;
const int N = 50;
int n,x;
int price[N];//价格
int sum_price[N];//前缀和
int ans = 1e9;
void dfs(int k,int sum)
{
    
    if(sum+sum_price[n]-sum_price[k-1]<x)//sum_price[n]-sum_price[k-1]为剩余节点的所有值的和
    {
        return;
    }
    if(sum>=x)
    {
        ans = min(sum,ans);//更新最小值
    }
    if(k>n)
    {
        return;
    }
    dfs(k+1,sum+price[k]);//选择这本书
    dfs(k+1,sum);//不选择这本书
}
int main()
{
    cin>>n>>x;
    for(int i=1;i<=n;i++)
    {
        cin>>price[i];
        sum_price[i]=sum_price[i-1]+price[i];//前缀和
    }
    dfs(1,0);//从第一本书开始
    cout<<ans<<endl;
}

你可能感兴趣的:(CCF-CSP,深度优先,算法,图论)