题目大意:
给你一堆砝码的质量和一个天平,利用砝码放在天平上可以称出物品的质量,问在1到所有砝码的质量之和的范围内有哪些整数数据是测不到的,如若没有输出0,
否则输出测不出的质量的个数,并在第二行的时候将其一个个输出
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1709
这题目我考虑的是用DP来做,因为每个砝码质量不大于100,数量不超过100,所以总和不会超过10000,我就给个稍微大于10000的dp数组即可。
dp[i]=1表示i质量能测出,dp[i]=0表示 i 质量测不出。
用一个m表示每次添入新的数据后能达到的质量的最大值。
对于每加入一个新的数据a[i+1],更新一次dp[],m也更新为m+=a[i+1]
因为砝码放在左和右都可以,所以对于已能称出的数据来说,新来的砝码(放在左边)看成加上它的数据,(那么右边)看成减去它的数据得到的绝对值即可
dp[j+a[i+1]]=1,dp[abs(j-a[i+1])]=1(j在1到m之间,且dp[j]==1)通过循环找到j,因为防止更新的dp[j]影响循环,我建了b[N]数组来保存每次得到的j的值
当然全部弄完以后要加上dp[a[i+1]]=1;因为它单独称也是成立的
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 #define MAXN 10005 8 int dp[MAXN],unValue[MAXN],b[105];//unValue来存不能测量出来的质量
9 10 int abs(int x) 11 { 12 return x>0?x:-x; 13 } 14 int main() 15 { 16 int N,a[101],m,cnt,k;//m作为每次dp后的最大值,cnt在后面表示不能称量出来的点的个数 17 while(scanf("%d",&N)!=EOF){ 18 for(int i=0;i<N;i++) 19 scanf("%d",&a[i]); 20 memset(dp,0,sizeof(dp)); 21 dp[a[0]]=1,m=a[0]; 22 for(int i=1;i<N;i++) 23 { 24 k=0;//k用来找到每次i循环能找到有多少个j已经能称出来的 25 for(int j=1;j<=m;j++) 26 { 27 if(dp[j]==1){ 28 b[k++]=j; 29 } 30 } 31 for(int j=0;j<k;j++) 32 { 33 dp[a[i]+b[j]]=1; 34 dp[abs(a[i]-b[j])]=1; 35 } 36 dp[a[i]]=1;//这2句要放在循环最后,不然会影响到前面的值 37 m+=a[i]; 38 } 39 cnt=0; 40 //寻找那些没能成功称出来的点 41 for(int i=1;i<=m;i++) 42 if(dp[i]==0) unValue[cnt++]=i; 43 if(cnt==0) cout<<0<<endl; 44 else{ 45 cout<<cnt<<endl; 46 for(int i=0;i<cnt-1;i++) 47 cout<<unValue[i]<<' '; 48 cout<<unValue[cnt-1]<<endl; 49 } 50 } 51 return 0; 52 }
我还在坚持,我还未达到我所想,梦~~一直在