牛客周赛 Round 31 E小红的子集取反

原题链接:E-小红的子集取反_牛客周赛 Round 31 (nowcoder.com)

题目大意:小红拿到了一个数组,她准备选择若干元素乘以 -1,使得最终所有元素的和为 0。小红想知道最少需要选择多少个元素?

思路:此问题类似与01背包,每个数只能操作一次,每次操作的代价可以记为1。

y总的dp分析方法可得到:

牛客周赛 Round 31 E小红的子集取反_第1张图片

直接看代码吧

#pragma GCC optimize(2)
#include
#define endl '\n' 
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair pii;
const int N=1e6+10;
ll n,f[220][80020];
int main()
{
    ios::sync_with_stdio(NULL);
    cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=0;i<=200;i++)
    {
        for(int j=0;j<=80000;j++)
        {
            f[i][j]=1e18;
        }
    }
    f[0][40000]=0;
    ll x;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        for(int j=0;j<=80000;j++)
        {
            if(j-x>=0&&j-x<=80000)f[i][j]=min(f[i][j],f[i-1][j-x]);//这个是图中状态转移的左边
            if(j+x>=0&&j+x<=80000)f[i][j]=min(f[i][j],f[i-1][j+x]+1);//这是图中状态转移的右边
        }
    }
    if(f[n][40000]!=1e18)cout<

附上一份dfs的代码(别用map会T!!!):

#pragma GCC optimize(2)
#include
#define endl '\n' 
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair pii;
const int N=1e6+10;
ll p[N],n;
ll op[220][80800];
ll dfs(ll x,ll k)
{
    if(op[x][k]!=0x3f3f3f3f3f3f3f3f)return op[x][k];
    if(x>n)
    {
        if(k==0)return 0;
        else return 1e18;
    }
    ll sum=0;
    sum=min(dfs(x+1,k+p[x]),dfs(x+1,k-p[x])+1);
    op[x][k]=sum;
    return sum;
}
int main()
{
    ios::sync_with_stdio(NULL);
    cin.tie(0),cout.tie(0);
    cin>>n;
    memset(op,0x3f,sizeof(op));
    for(int i=1;i<=n;i++)cin>>p[i];
    ll k=dfs(0,0);
    if(k==1e18)cout<<-1;
    else cout<

你可能感兴趣的:(算法,数据结构,求职招聘)