有n堆卡片,每堆卡片的张数不同,总的张数不一定是n的倍数。在任意两堆卡片之间,移动任意张卡片,最终目标是让最多一堆的卡片张数与最少一堆的卡片张数的差小于等于1。规定将第i堆上的一张卡片移动到第j堆上,或者相反移动,代价均为|i-j|。用动态规划算法计算均分纸牌的代价。例如当n=5,每堆张数分别是5,9,2,12,9时,最小移动代价是8。代码如下
请问
1.解释dp[i][j]的含义
2.如何理解代码中A、B行的状态转移方程
3.题目中从第i堆移动一张卡片到第j堆上,或者相反移动,代价均为|i-j|,在程序中是如何计算|i-j|的
部分代码如下:
const int M=10;
long dp[M][M],card[M],s[M];
int main(){
int n,i,j;
cin>>n;
for (i=1;i<=n;i++){
cin>>card[i];
s[i]=s[i-1]+card[i];
}
int r=s[n]%n,q=s[n]/n;
for(i=1;i<=n;++i){
for(j=0;j<=r;++j){
int c=abs(s[i]-q*i-j);
dp[i][j]=dp[i-1][j]+c;//A
if(j)
dp[i][j]=min(dp[i-1][j-1]+c,dp[i][j]);//B
}
}
cout<<dp[n][r]<<endl;
return 0;
}