zoukankan      html  css  js  c++  java
  • bzoj1042: [HAOI2008]硬币购物(DP+容斥)

      1600+人过的题排#32还不错嘿嘿

      浴谷夏令营讲过的题,居然1A了

      预处理出f[i]表示购买价值为i的东西的方案数

      然后每次询问进行一次容斥,答案为总方案数-第一种硬币超限方案-第二种超限方案-第三种超限方案-第四种超限方案+第一种和第二种硬币超限方案+...

      第i种硬币超限方案就是f[s-c[i]*(d[i]+1)],其他的类推一下就行了

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio> 
    #include<algorithm>
    #define ll long long 
    using namespace std;
    const int maxn=100010,inf=1e9;
    int n,mx;
    ll ans;
    int c[5],d[maxn][5],s[maxn];
    ll f[maxn];
    void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    void dfs(int fir,int dep,int sum,int last)
    {
        for(int i=last;i<=4;i++)
        {
            if(sum+c[i]*(d[fir][i]+1)>s[fir])continue;
            if(dep&1)ans-=f[s[fir]-sum-c[i]*(d[fir][i]+1)];
            else ans+=f[s[fir]-sum-c[i]*(d[fir][i]+1)];
            dfs(fir,dep+1,sum+c[i]*(d[fir][i]+1),i+1);
        }
    }
    int main()
    {
        for(int i=1;i<=4;i++)read(c[i]);read(n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=4;j++)read(d[i][j]);
            read(s[i]);mx=max(mx,s[i]);
        }
        f[0]=1;
        for(int i=1;i<=4;i++)
        for(int j=c[i];j<=mx;j++)
        f[j]+=f[j-c[i]];
        for(int i=1;i<=n;i++)
        {
            ans=f[s[i]];
            dfs(i,1,0,1);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    android选择时间攻略
    安卓通知的基本用法
    个人作业----软件工程实践总结
    第三次作业——《K米评测》
    第二次结对编程作业——毕设导师智能匹配
    原型设计与需求分析
    作品调研
    软件工程的实践项目课程的自我目标
    软件工程实践总结作业20161231
    K米测试
  • 原文地址:https://www.cnblogs.com/Sakits/p/7455582.html
Copyright © 2011-2022 走看看