题目大意:给出一个正整数M,给出N个正整数ai,让你在这些数中挑出一些数组成M的一个划分,如果符合条件的划分数超过两个,输出:-1,如果没有输出:0,如果有且仅有一个:则按顺序输出剩下的数的序号。

例如:

input output
270
4
100
110
170
200
2 4
270
4
100
110
160
170
-1
270
4
100
120
160
180
0

测例1中,有且仅有100+170=270,所以输出110与200的序号2 4。测例2中,100+170=160+110=270,所以输出-1。测例3中,没有任何两个数的和为270,所以输出0。

Time Limit:500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

数据规模:0<ai<=1000,2<=N<=100。

理论基础:无。

题目分析:我们用dp[i][j]表示仅用前i个数可以挑出的j的划分的个数。pre[i][j]表示第i个数被选择或者未被选择,用于最后输出结果。

我们可以得出如果需要输出时,那么方案数就是唯一的,所以途径的所有的状态的数都只能是被选或者未被选择,所以我们不用担心,a[i]被选与未被选都有解的情况。因为这时我们不需要输出。

下来是状态转移方程:dp[i][j]=dp[i-1][j]+(j>=a[i])*(dp[i-1][j-a[i]]);在每一层dp时,只要发现dp[i][M]大于等于2即可输出-1退出程序。

如果dp[N][M]为0,则输出0。否则,回溯找回答案并输出。

代码如下:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<ctime>
#include<vector>
using namespace std;
typedef double db;
#define DBG 0
#define maa (1<<31)
#define mii ((1<<31)-1)
#define ast(b) if(DBG && !(b)) { printf("%d!!|\n", __LINE__); while(1) getchar(); } //调试
#define dout DBG && cout << __LINE__ << ">>| "
#define pr(x) #x"=" << (x) << " | "
#define mk(x) DBG && cout << __LINE__ << "**| "#x << endl
#define pra(arr, a, b) if(DBG) {\
dout<<#arr"[] |" <<endl; \
for(int i=a,i_b=b;i<=i_b;i++) cout<<"["<<i<<"]="<<arr[i]<<" |"<<((i-(a)+1)%8?" ":"\n"); \
if((b-a+1)%8) puts("");\
}
template<class T> inline bool updateMin(T& a, T b) { return a>b? a=b, true: false; }
template<class T> inline bool updateMax(T& a, T b) { return a<b? a=b, true: false; }
typedef long long LL;
typedef long unsigned int LU;
typedef long long unsigned int LLU;
#define N 100
#define M 100000
int dp[N+1][M+1];
int a[N+1],sum,n,cnt,ans[N+1];
bool pre[N+1][M+1];
int main()
{
scanf("%d%d",&sum,&n);
for(int i=1;i<=n;i++)scanf("%d",a+i);
dp[1][0]=1,dp[1][a[1]]=1,pre[1][a[1]]=true;
for(int i=2;i<=n;i++)
{
for(int j=0;j<=sum;j++)
{
dp[i][j]=dp[i-1][j]+(j>=a[i])*dp[i-1][j-a[i]];
if(dp[i-1][j-a[i]])pre[i][j]=true;
}
if(dp[i][sum]>=2)
{
printf("-1\n");
return 0;
}
}
if(dp[n][sum]==0)
{
printf("0\n");
return 0;
}
if(dp[n][sum]==1)
{
for(int i=n;i>=1;i--)
{
if(!pre[i][sum])ans[++cnt]=i;
sum=sum-a[i]*pre[i][sum];
}
pra(ans,1,cnt)
for(int i=cnt;i>=1;i--)
{
printf("%d%c",ans[i],i==1?'\n':' ');
}
}
return 0;
}

其中的初始化细节处理很容易理解,所以不用再细说了。

by:Jsun_moon http://blog.csdn.net/jsun_moon

URAL 1244的更多相关文章

  1. DP URAL 1244 Gentlemen

    题目传送门 /* 题意:已知丢失若干卡片后剩余的总体积,并知道原来所有卡片的各自的体积,问丢失的卡片的id DP递推:首先从丢失的卡片的总体积考虑,dp[i] 代表体积为i的方案数,从dp[0] = ...

  2. 递推DP URAL 1244 Gentlemen

    题目传送门 /* 题意:给出少了若干卡片后的总和,和原来所有卡片,问少了哪几张 DP:转化为少了的总和是否能有若干张卡片相加得到,dp[j+a[i]] += dp[j]; 记录一次路径,当第一次更新的 ...

  3. ural 1244. Gentlemen

    1244. Gentlemen Time limit: 0.5 secondMemory limit: 64 MB Let's remember one old joke: Once a gentle ...

  4. URAL 1244. Gentlemen(DP)

    题目链接 这题不难啊...标记一下就行了.表示啥想法也没有. #include <cstring> #include <cstdio> #include <string& ...

  5. URAL 1244. Gentlemen (DP)

    题目链接 题意 : 给出一幅不完全的纸牌.算出哪些牌丢失了. 思路 : 算是背包一个吧.if f[j]>0  f[j+a[i]] += f[j];然后在记录一下路径. #include < ...

  6. URAL DP第一发

    列表: URAL 1225 Flags URAL 1009 K-based Numbers URAL 1119 Metro URAL 1146 Maximum Sum URAL 1203 Scient ...

  7. 【51Nod 1244】莫比乌斯函数之和

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1244 模板题... 杜教筛和基于质因子分解的筛法都写了一下模板. 杜教筛 ...

  8. 51nod 1244 莫比乌斯函数之和

    题目链接:51nod 1244 莫比乌斯函数之和 题解参考syh学长的博客:http://www.cnblogs.com/AOQNRMGYXLMV/p/4932537.html %%% 关于这一类求积 ...

  9. 后缀数组 POJ 3974 Palindrome && URAL 1297 Palindrome

    题目链接 题意:求给定的字符串的最长回文子串 分析:做法是构造一个新的字符串是原字符串+反转后的原字符串(这样方便求两边回文的后缀的最长前缀),即newS = S + '$' + revS,枚举回文串 ...

随机推荐

  1. 让jquery easyui datagrid列支持绑定嵌套对象

    嵌套对象是指返回的json数据,是对象的某个属性自带有属性.而我们恰恰又需要这个属性,默认情况下easyui的datagrid是不支持绑定嵌套对象的.比如:datagrid的field属性只能为fie ...

  2. JavaScript 总结

    1. JavaScript prototype属性是一个对象 当一个函数在定义之后 就会自动获得这个属性.其初始值是一个空对象.新建了一个名为Cat的构造函数,其prototype为一个对象,cons ...

  3. Mac搭建Git/GitHub全过程

    在GitHub上注册了账号,建立了第一个hello-world repository,然后打算把Git平台配置在自己的机器上.因为是Mac OS,我也是一个初学者,很多功能需要自己摸索,于是各种百度, ...

  4. i利用图片按钮 和 input type="image" 为背景提交表单

    <img src="img/cancel.jpg" onclick="javascript:document.getElementByIdx_x('loginFor ...

  5. NYOJ-571 整数划分(三)

    此题是个非常经典的题目,这个题目包含了整数划分(一)和整数划分(二)的所有情形,而且还增加了其它的情形,主要是用递归或者说是递推式来解,只要找到了递推式剩下的任务就是找边界条件了,我觉得边界也是非常重 ...

  6. 手工释放Linux内存

    转载自:http://blog.csdn.net/wyzxg/article/details/7279986/ linux的内存查看: [root@localhost 0.1.0]# free -m  ...

  7. Visual Studio写的项目在 IIS 服务器上运行的两种简单方法

    首先需要PC上开启了IIS服务,相关方法网上很多,也很简单 第一种:直接在项目中操作 1.创建一个项目,然后右击选中项目,右击,单击属性,打开项目属性标签页面 如图,选择Web标签,在服务器栏目中选中 ...

  8. mysql limit性能问题

    offset大的时候的比较 1. SELECT * FROM persons LIMIT 200000,10; 耗时0.109s 2. SELECT *FROM persons WHERE id> ...

  9. 获取android手机联系人信息

    package com.yarin.android.Examples_04_04; import android.app.Activity; import android.database.Curso ...

  10. GridView、Repeater获取当前行号

    GridView: <%# Container.DataItemIndex+1 %> Repeater:<%# Container.ItemIndex+1%>