131014 Regionals 2010, North America - Mid-Atlantic USA

来源:互联网 发布:中国对外工程承包数据 编辑:程序博客网 时间:2024/05/16 08:08

H题:这题是一个变形的背包问题,注意两点:

1.数组开dp[2][],记录前一转态和后一个状态,否则超内存。

2.求最小值,这样能节省时间。

代码:

#include<iostream>#include<cstdio>#define maxn 1005#define maxf 20005#define INF 1000000using namespace std;int n,k,l,F;int f[maxn],d[maxn];int dp[2][maxf];int DP(){    int ans=0;    dp[0][0]=0;    for(int i=1;i<=F;i++)    {        dp[0][i]=INF;    }    for(int i=1;i<=n;i++)    {        for(int j=F;j>=0;j--)        {            dp[1][j]=INF;            //看第i个东西            if(j-f[i]>=0&&dp[0][j-f[i]]+d[i]<=l)            {                dp[1][j]=min(dp[1][j],dp[0][j-f[i]]+d[i]);            }            //不看第i个东西            if(dp[0][j]!=INF)            dp[1][j]=min(dp[1][j],max(0,dp[0][j]-k));            dp[0][j]=dp[1][j];        }    }    for(int i=F;i>=0;i--)    {        if(dp[1][i]!=INF)        {            ans=i;            break;        }    }    return ans;}int main(){    while(scanf("%d%d%d",&n,&k,&l)!=EOF)    {        if(!n&&!k&&!l) break;        F=0;        for(int i=1;i<=n;i++)        {            scanf("%d%d",&f[i],&d[i]);            F+=f[i];        }        printf("%d\n",DP());    }    return 0;}
B题:这题是一个数位dp的题,主要是数位dp写的太少,基本上模式都一样。

代码:

#include<iostream>#include<cstdio>#include<cstring>#define maxn 1005#define maxf 20005#define INF 1000000#define ll long longusing namespace std;int k;int bit[100],ans[100];ll vis[100][100];void init(){    ans[0]=-111;    ans[1]=0;    for(int i=2;i<=100;i++)    {        int x=i,cnt=0;        while(x)        {            if(x%2)            cnt++;            x/=2;        }        ans[i]=ans[cnt]+1;    }}//下标 前面1的个数 前一位是否取最高位 前面是否全是0 当前数是1ll dfs(int p,int num,int a,int b,int c){    if(p==0)    {        if(c==1) return k==0;        else return ans[num]+1==k;    }    if(a==0&&vis[p][num]>=0)    {        return vis[p][num];    }    ll ret=0;    int size=a?bit[p]:1;    for(int i=0;i<=size;i++)    {        ret+=dfs(p-1,num+(i==1),a&&(i==size),b&&(i==0),b&&(i==1));    }    return a?ret:vis[p][num]=ret;}ll solve(ll x){    if(x<=0) return 0;    if(x==1) return k==0;    int cnt=0;    while(x)    {        bit[++cnt]=x%2;        x/=2;    }    return dfs(cnt,0,1,1,0);}int main(){    ll l,r;    init();    while(scanf("%lld%lld%d",&l,&r,&k)!=EOF)    {        if(!l&&!r&&!k) break;        memset(vis,-1,sizeof(vis));        ll ret=solve(r)-solve(l-1);        printf("%lld\n",ret);    }    return 0;}


原创粉丝点击