【poj 1722 】SUBTRACTo

来源:互联网 发布:淘宝如何引流推广 编辑:程序博客网 时间:2024/06/05 03:34

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 10000using 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;} 


0 0
原创粉丝点击