您的位置:首页 > 其它

POJ 1745 Divisibility

2013-03-16 22:59 375 查看
 

链接:http://poj.org/problem?id=1745

题意:给定N个数,问进行加减运算之后的结果是否能被K整除。

 

分析:DP。设布尔型数组dp[][],dp[i][j]表示对前i个数进行加减运算的结果模K的值为j。共N个阶段,每个阶段K个状态。

状态转移方程为:if(dp[i-1][j])      dp[i][abs(j+num[i])%k]=true;

                                                  dp[i][abs(j-num[i])%k]=true;

初始条件:dp[0][0]=true;

 

Souce Code:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int N=10005,K=105;
int num
,n,k;
bool dp
[K];

void Init(){
int i;
scanf("%d %d",&n,&k);
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
memset(dp,false,sizeof(dp));
dp[0][0]=true;
}

bool solve(){
int i,j;
for(i=1;i<=n;i++){
for(j=0;j<k;j++){
if(dp[i-1][j]){
dp[i][abs(j+num[i])%k]=true;
dp[i][abs(j-num[i])%k]=true;
}
}
}
return dp
[0];
}

int main()
{
Init();
if(solve()) printf("Divisible\n");
else        printf("Not divisible\n");
return 0;
}


 

 

由以上状态转移方程易知求解到的过程中只与相邻的两行有关,因此可以用滚动数组优化空间复杂度。

(对于滚动数组,一定要注意避免之前的处理对后续处理的影响!具体见代码。)

 

Source Code:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;

const int K=105;
bool dp[2][K];
int num[10005],n,k;

void Init(){
int i;
scanf("%d %d",&n,&k);
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
memset(dp,false,sizeof(dp));
dp[0][0]=true;
}

bool solve(){
int i,j;
for(i=1;i<=n;i++){
for(j=0;j<k;j++)
dp[i&1][j]=false;//当前要处理的行要全部清0,以免之前的处理对此产生影响!
for(j=0;j<k;j++){
if(dp[(i-1)&1][j]){
dp[i&1][abs(j+num[i])%k]=true;
dp[i&1][abs(j-num[i])%k]=true;
}
}
}
return dp[n&1][0];
}

int main()
{
Init();
if(solve()) printf("Divisible\n");
else        printf("Not divisible\n");

return 0;
}


 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: