动态规划的一道题目,看了别人的代码之和自己实现的。首先是读入数据,统计每一堆中不同大小盘子的个数以及所有的盘子中大小不同的个数。然后统计对于每一类的盘子存在于哪些堆中以及每一堆中存在着哪些种类的盘子。紧接着,开始动态规划的过程,利用dp[i][j]表示将第1~i类的盘子全部堆好,并且最终这些盘子是放置于第j堆中,那么在堆积第i类的盘子之前肯定需要把第i-1类的盘子堆积好,所以当我们选取的第i类盘子最终的落脚点和第i-1类的盘子的最终的落脚点不同的时候,那么肯定是选取dp[i-1][k]+int(G[i].size())-exist[k][i]?1:0的最小值,当选取的第i类盘子和第i-1类盘子最终的落脚点相同的时候就选取 dp[i-1][k],并且比较得出最小值。注意上面的这种情况是当G[i]的大小为1的时候。当G[i]大小不为1的时候,出于避免重复的考虑(个人理解,如果有其他的理解欢迎在评论区交流),就直接舍弃这种情况,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
using namespace std;
set<int> G[2510];//第i类盘子所存在的堆的编号
int exist[55][2510];//第i堆中是否存在第j类的盘子
int dp[2510][55];
class Solve{
public:
int n;
int plate[55][55];
int total[2510];
int ind,amount;
int Inf = 1047483647;
void Init(){
ind = 0;
memset(exist,0,sizeof(exist));
for (int i = 0; i < 2510; i++) G[i].clear();
for (int i = 1; i <= n; i++){
cin >> plate[i][0];
for (int j = 1; j <= plate[i][0]; j++){
cin >> plate[i][j];
total[++ind] = plate[i][j];
}
plate[i][0] = unique(plate[i] + 1, plate[i] + 1 + plate[i][0]) - (plate[i]+1);
}
sort(total+1,total+ind+1);
amount = unique(total+1, total + ind+1) - (total+1);
for (int i = 1; i <= n; i++){
for (int j = 1; j <= plate[i][0]; j++){
plate[i][j] = lower_bound(total+1, total +1 + amount, plate[i][j]) - total;
G[plate[i][j]].insert(i);
exist[i][plate[i][j]] = 1;
}
}
}
void Deal(){
Init();
memset(dp,0x3f,sizeof(dp));
for (int i : G[1]) dp[1][i] = G[1].size() - 1;
for (int i = 2; i <= amount; i++){
for (int j : G[i]){
for (int k : G[i - 1]){
if (j != k){
dp[i][j] = min(dp[i][j], dp[i - 1][k] + int(G[i].size()) - (exist[k][i] ? 1 : 0));
}
else{//j==k
dp[i][j] = min(dp[i][j], (G[i].size() == 1 )? dp[i - 1][j] : Inf);
}
}
}
}
int ans = Inf;
for (int j = 1; j <= n; j++) ans = min(ans, dp[amount][j]);
cout << ans*2-(n-1) << endl;
}
};
int main(){
Solve a;
int Case = 1;
while (cin >> a.n){
cout << "Case " << Case++ << ": ";
a.Deal();
}
return 0;
}