超级码力在线编程大赛初赛 第3场 2.房屋染色
https://tianchi.aliyun.com/oj/15179470890799741/85251759933690470
数据范围比较小,可以想到枚举主题步行街的长度和颜色
nf[i][j]表示前i间房屋已染色,第i间房屋不染颜色j的最小花费
ng[i][j]表示第i间及其之后的房屋已染色,第i间房屋不染颜色j的最小花费
s[i][j]表示前i间房屋都染颜色j的花费
枚举主题步行街起点i,终点j,颜色k
答案就是 min{ s[j][k]-s[i-1][k]+nf[i-1][k]+ng[i+1][k] }
求nf:
f[i][j]表示前i间房屋已染色,第i间房屋染颜色j的最小花费
nf[i][j]=min{ f[i][k] } k≠j
求ng同理
时间复杂度 O(n*m*t+n*m*m)
#include<cstdio> #include<vector> #include<iostream> #include<algorithm> using namespace std; #define N 102 int f[N][N],g[N][N],nf[N][N],ng[N][N],s[N][N]; int paintHouseIII(vector<vector<int> > &costs, int t) { // Write your code here. int n=costs.size(),m=costs[0].size(); for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) { f[i][j]=1e7; g[i][j]=1e7; nf[i][j]=1e7; ng[i][j]=1e7; } } for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int k=1;k<=m;++k) if(k!=j) f[i][j]=min(f[i][j],f[i-1][k]+costs[i-1][j-1]); for(int i=n;i;--i) for(int j=1;j<=m;++j) for(int k=1;k<=m;++k) if(k!=j) g[i][j]=min(g[i][j],g[i+1][k]+costs[i-1][j-1]); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int k=1;k<=m;++k) if(j!=k) { nf[i][j]=min(nf[i][j],f[i][k]); ng[i][j]=min(ng[i][j],g[i][k]); } for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) s[i][j]=s[i-1][j]+costs[i-1][j-1]; int ans=1e7; for(int i=1;i<=n;++i) for(int j=i;j-i+1<=t && j<=n;++j) for(int k=1;k<=m;++k) ans=min(ans,s[j][k]-s[i-1][k]+nf[i-1][k]+ng[j+1][k]); return ans; } int main() { vector<vector<int> >c; vector<int>cc; int n,m,x; scanf("%d%d",&n,&m); for(int i=0;i<n;++i) { cc.clear(); for(int j=0;j<m;++j) { scanf("%d",&x); cc.push_back(x); } c.push_back(cc); } scanf("%d",&x); printf("%d",paintHouseIII(c,x)); }