poj 3971 Scales (数位dp,好题)

题意:

给出一个二进制形式的重量的物品,现在有n个砝码分别是2^0、2^1....2^(n-1)。现在问如何在天平上放砝码可以使得天平平衡。

题解:

我们分析,假设我们左边放的砝码重量总和为x,右边放的重量总和为y(左边还有放物品)。

那么问题就转化重量为w的物品加砝码能变成那些可行重量的问题。我们根据物品的重量的二进制来求解,按位dp。dp[i][2],0表示进位,1表示不进位。这样分两个大类来考虑:

1、这一位是'0'

(1)这位不进位dp[i][0]=dp[i-1][0]+dp[i-1][1]

(2)这位进位dp[i][1]=dp[i-1][1]

2、这一位是'1'

(1)这位不进位dp[i][0]=dp[i-1][0]

(2)这位进位dp[i][1]=dp[i-1][0]+dp[i-1][1]

状态方程要好好思考,不多做解释。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const int MOD=1000000007;
const int maxn=5100;
const int maxm=21000;
ll dp[1000005][2];
char bit[1000005];

int main(){
    //freopen("E:\\read.txt","r",stdin);
    int n,l,d,T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d %d",&n,&l,&d);
        scanf("%s",bit+1);
        for(int i=1;i<=l/2;i++)
            swap(bit[i],bit[l-i+1]);
        for(int i=l+1;i<=n;i++)
            bit[i]='0';
        memset(dp,0,sizeof dp);
        dp[0][0]=1;
        for(int i=1;i<=n;i++){
            if(bit[i]=='0'){
                add(dp[i][0],dp[i-1][0]+dp[i-1][1],d);
                add(dp[i][1],dp[i-1][1],d);
            }else{
                add(dp[i][0],dp[i-1][0],d);
                add(dp[i][1],dp[i-1][0]+dp[i-1][1],d);
            }
        }
        printf("%I64d\n",dp[n][0]);
    }
    return 0;
}




你可能感兴趣的:(poj 3971 Scales (数位dp,好题))