POJ 1745 Divisibility 类似0-1背包DP
类似背包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; }


浙公网安备 33010602011771号