poj1745 Divisibility

本文介绍了一种使用动态规划解决整数序列通过添加运算符使其结果能被特定值整除的问题的方法。通过两个实现案例,展示了如何利用DP减少内存消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给你一列整数,在整数间加‘ + ’ 或 ‘ - ‘,使这个算式的值能被k整除。

用dp[ i ][ j ] 表示加上或减去第 i 个数后,所得值取模后的值能否为 j ,所以dp为bool型即可。

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

                         dp[ i ][ abs( j -  num[i]) % k] = true; (当然,必须满足dp[ i - 1 ][ j ] == true, 才能进行状态转移)

边界条件:dp[ 0 ][ 0 ] = true;

时间效率不高:235ms 不知道大牛的0ms怎么做出来的

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

#define N 10002
#define K 102

int num[N], n, k;
bool dp[N][K];

void Init()
{
   int i;

   scanf("%d%d", &n, &k);
   for(i = 1; i <= n; i++)
	   scanf("%d", &num[i]);
}

bool Solve()
{
	int i, j;

	memset(dp, false, sizeof(dp));
	dp[0][0] = true;
	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[n][0];
}

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


发现别人的内存很小,一看状态转移方程,当前行只与上一行的值有关,原来可以开滚动数组。219ms


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

#define N 10002
#define K 102

int num[N], n, k;
bool dp[2][K];

void Init()
{
   int i;

   scanf("%d%d", &n, &k);
   for(i = 1; i <= n; i++)
	   scanf("%d", &num[i]);
}

bool Solve()
{
	int i, j;

	memset(dp, false, sizeof(dp));
	dp[0][0] = true;
	for(i = 1; i <= n; i++){
		for(j = 0; j < k; j++) // 开滚动数组之后与之前代码的不同之处,必须对当前正在处理的
			dp[i%2][j] = false;// 第i行重新赋值为false,避免之前得到的值对当前造成影响
		for(j = 0; j < k; j++){
			if(dp[1-i%2][j]){
			   dp[i%2][abs(j + num[i]) % k] = true;
			   dp[i%2][abs(j - num[i]) % k] = true;
			}
		}
	}
	return dp[n%2][0];
}

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


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值