131014 Regionals 2010, North America - Mid-Atlantic USA

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

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

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

代码:

#include<iostream>
#include<cstdio>
#define maxn 1005
#define maxf 20005
#define INF 1000000
using 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 long
using 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 当前数是1
ll 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;
}


你可能感兴趣的:(131014 Regionals 2010, North America - Mid-Atlantic USA)