【poj 1722 】SUBTRACTo

本文介绍了一种解决特定数列加减法问题的方法,通过动态规划算法确定数列中元素的加减顺序,以达到目标值。文章详细解释了状态转移方程,并提供了完整的C++代码实现。

OK,拿到这道题的时候思路还是蛮清晰的,因为可以非常明显的发现就是不断更改减法的顺序其实并没有改变序列中的值,而仅仅改变的是这个数之前的加或者减(加变减,减变加)所以,问题变成了求一个合法的添加加减顺序使得整个数列得到想要的答案。

这里有参考其他题解:

首先定义 f[ i ][ j ]表示前i个数为止通过加减能否得到j这一个数,如果答案为1则表示通过减得到2就表示 通过加得到0表示无法得到

最后就是答应路径,一开始以为挺麻烦的,后来发现并不是这么一回事,自己在草稿纸上多演算几次就可以发现一个规律:如果前面是+就一定要先运算最后剩下的全部输出1就ok了

最后,有一个地方坑了我几次,就是 

if()

else if()

原来直接用的事两个if 而后来发现j是不断更新的一开始不满足的条件更新后可能会满足,总之多用else

#include<cstdio>
#include<cstring>
#include<iostream>
#define fix 10000
using namespace std;
int n , m , f[125][20020],pre[122],cur[122];


int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		for(int i=1;i<=n;i++)scanf("%d",cur+i);
		memset(f,0,sizeof(f));
		memset(pre,0,sizeof(pre));
		f[2][cur[1]-cur[2]+fix]=1;
		for(int i=3;i<=n;i++){
			for(int j=0;j<=20000;j++){
				if(f[i-1][j]>0){
					if(j+cur[i]<=20000)f[i][j+cur[i]]=2;
					if(j-cur[i]>=0)f[i][j-cur[i]]=1;
				}
			}
		}
		
		for(int i=n,j=m+fix;i>=1;i--){
			if(f[i][j]==1){
				pre[i]=1;
				j+=cur[i];
			}
			 else if(f[i][j]==2){
				pre[i]=2;
				j-=cur[i];
			}
		}
		int cnt=0;
		for(int i=2;i<=n;i++){
			if(pre[i]==2){
				printf("%d\n",i-cnt-1);
				cnt++;
			}
		}
		for(int i=2;i<=n;i++)if(pre[i]==1)puts("1");
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值