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 }