POJ 1745 Divisibility 类似0-1背包DP

来源:互联网 发布:backtrack5软件下载 编辑:程序博客网 时间:2024/05/18 18:53

类似背包DP。

用dp[i][j](bool类型)来表示前i个数组成的和对k取模的值是否存在;

状态转移方程为:

if(dp[i-1][j])dp[i][get(tmp-j)]=dp[i][get(tmp+j)]=1;//get:自己写个取模函数,注意负数取模-5%7=2

AC代码:

View Code
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;bool dp[10003][103];int k;int get(int x){    return x < 0 ? -x%k: x%k;}int main(){    int n,tmp, i, j;    while(~scanf("%d%d",&n,&k))    {        memset(dp,0,sizeof(dp));        scanf("%d",&tmp);        dp[1][get(tmp)]=1;        for(i=2;i<=n;i++)        {            scanf("%d",&tmp);            for(j=0;j<k;j++)            if(dp[i-1][j])dp[i][get(tmp-j)]=dp[i][get(tmp+j)]=1;        }        if(dp[n][0])printf("Divisible\n");        else printf("Not divisible\n");    }    return 0;}

 

 

滚动数组版,节省内存(第一次用,不错):

 

状态转移方程为:

for(j=0;j<k;j++)if(dp[g1][j])dp[g2][get(j-tmp)]=dp[g2][get(j+tmp)]=1;//g1,g2表示两种状态

 

AC代码:

View Code
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;bool dp[2][103];int n, k;int get(int x){    return x < 0 ? -x%k : x%k;}int main(){    int tmp, i, j;    while(~scanf("%d%d",&n,&k))    {        int g1=0,g2=1;        memset(dp,0,sizeof(dp));        scanf("%d",&tmp);        dp[0][get(tmp)]=1;        for(i=2;i<=n;i++)        {            scanf("%d",&tmp);            for(j=0;j<k;j++)//注意将状态g2先清零            dp[g2][j]=0;            for(j=0;j<k;j++)            if(dp[g1][j])dp[g2][get(j-tmp)]=dp[g2][get(j+tmp)]=1;            g1=!g1;g2=!g2;        }           if(dp[g1][0])printf("Divisible\n");        else printf("Not divisible\n");    }    return 0;}

 

 

原创粉丝点击