题意:给成一组多米诺牌,每个多米诺牌由上面和下面两组数组成,现要求可以翻动颠倒上下,使得多米诺上边的点数和减去下边的点数和的绝对值最小。
思路:不知道自己写的开两个数组的为什么一直wa。照抄了一个同样思路的代码能AC,错误在哪?????
AC代码:
#include <stdio.h> #include <string.h> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define N 52010 int dp[N],num[N],s[N/6],t[N/6]; int n; int main(){ int i,j,m,sum; sum = 0; memset(dp,-1,sizeof(dp)); dp[0] = 0; scanf("%d",&n); while(n--){ int a,b,i,j; scanf("%d %d",&a,&b); sum += a+b; for(j = sum;j>=0;j--){ if(dp[j] != -1){ int temp = dp[j]; dp[j] = -1; if(dp[j+a]==-1 || dp[j+a]>temp) dp[j+a] = temp; if(dp[j+b]==-1 || dp[j+b]>temp+1) dp[j+b] = temp+1; } } } for(i = sum/2;i>=0;i--) if(dp[i]!=-1){ printf("%d\n",min(dp[i],dp[sum-i])); break; } return 0; }
#include <stdio.h> #include <string.h> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define N 52010 int dp[N],num[N],s[N/6],t[N/6]; int n; int main(){ int i,j,m,sum; m = sum = 0; scanf("%d",&n); memset(dp, 0, sizeof(dp)); dp[0] = 1; for(i = 1;i<=n;i++){ scanf("%d %d",&s[i],&t[i]); m += max(s[i],t[i]); sum += (s[i]+t[i]); } for(i = 1;i<=m;i++) num[i] = n+1; for(i = 1;i<=n;i++) for(j = m-1;j>=0;j--) if(dp[j]){ dp[j+s[i]] = 1; num[j+s[i]] = min(num[j+s[i]],num[j]); dp[j+t[i]] = 1; num[j+t[i]] = min(num[j+t[i]],num[j]+1); dp[j] = 0; num[j] = n+1; } for(i = sum/2;i>=0;i--){ if(dp[i] && (j=min(num[i],num[sum-i])) != n+1){ printf("%d\n",j); break; } } return 0; }