ooj1057: M的整数倍DP

http://121.249.217.157/JudgeOnline/problem.php?id=1057

 

1057: M的整数倍

时间限制: 1 Sec  内存限制: 64 MB
提交: 130  解决: 33
[提交][状态][讨论版]

题目描述

给定N个数,选出任意多的数(每个数只能选一次),使其和为M的整数倍。问最少需要选几个数。

 

输入

第一行输入一个数T代表测试用例组数(T<=10),接下来T组测试用例,每组测试用例第一行为整数M, N(1<=M, N<=1000);接下来N行每行一个数,分别代表N个数之一。

 

输出

对于每组测试用例,输出满足条件最少需要选几个数,若没有解输出-1。每行输出一个结果。

 


样例输入

2
4 3
1
1
1
2 2
2
4

样例输出

-1
1

提示

 

来源

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<cstdlib>
 8 #include<queue>
 9 #include<vector>
10 #include<set>
11 using namespace std;
12 int t,m,n,dp[1010],a[1010],sign[1010][1010],temp;
13 #define inf 20000000
14 int main()
15 {
16     scanf("%d",&t);
17     while(t--)
18     {
19         memset(dp,0,sizeof(dp));
20         memset(a,0,sizeof(a));
21         memset(sign,0,sizeof(sign));
22         scanf("%d%d",&m,&n);
23         for(int i=1; i<=n; i++)
24             scanf("%d",&a[i]);
25         for(int i=0; i<m; i++)
26             dp[i]=inf;
27         for(int i=1; i<=n; i++)
28         {
29             dp[a[i]%m]=1;//至少几个数才可以使余数为(a[i]%m)   相当于初始化数组
30             sign[a[i]%m][i]=1;//记录余数为(a[i]%m),用到了啊【i】为1
31         }
32         for(int i=0; i<m; i++)
33         {
34             for(int j=1; j<=n; j++)
35             {
36                 temp=(i+a[j])%m;
37                 if(sign[i][j]==0&&dp[temp]>dp[i]+1)
38                 {
39                     dp[temp]=dp[i]+1;
40                     for(int k=1; k<n; k++) sign[temp][k]=sign[i][k];
41                     sign[temp][j]=1;
42                 }
43             }
44         }
45         if(dp[0]==inf)
46             printf("-1\n");
47         else
48             printf("%d\n",dp[0]);
49     }
50     return 0;
51 }

 

第二届“朗讯杯”初级组

[提交][状态][讨论版]
posted @ 2015-06-01 22:34  zach96  阅读(285)  评论(0编辑  收藏  举报