这个题说的是,有n个长度为m的01串,按一定顺序填到对应的m个坑里,假设某次填坑,有k个坑之前没填过1,那么就会产生k*k的花费。问如何安排顺序使得花费最少。
dp。其实每次填坑,花费和填坑顺序没有太大关系,只需要关心之前哪些坑被填过1就行了。从另一个角度理解,其实不一定要填完n个串,只需要填上n个串出现过的所有1就可以了。那么就可以弄一个m位二进制来dp,外循环是坑的状态,内循环扫一遍所有串,尝试填进去。
现在打TC的div1还真是吃力。。基本都是爆零。今天摸索了一会才知道如何在practice room里测题。
// BEGIN CUT HERE
// END CUT HERE
#line 5 "OrderOfOperations.cpp"
#include <string>
#include <vector>
#include <bitset>
#include <iostream>
using namespace std;
int dp[1050000];
const int INF = 1000000000;
int fun(vector<string> s){
int n=s.size();
if(n==0)return 0;
int m=s[0].size();
int t=1<<m;
for(int i=0;i<t;i++){
dp[i]=INF;
}
int val[n+10];
for(int i=0;i<n;i++){
bitset<20> b(s[i]);
val[i]=b.to_ulong();
}
dp[0]=0;
for(int i=0;i<t;i++){
for(int j=0;j<n;j++){
int res=i|val[j];
int NEW=val[j]&(~i);
bitset<20> tmp(NEW);
NEW=tmp.count();
dp[res]=min(dp[res],dp[i]+NEW*NEW);
}
}
int all=0;
for(int i=0;i<n;i++){
all|=val[i];
}
return dp[all];
}
class OrderOfOperations {
public:
int minTime(vector <string> s) {
return fun(s);
}
};