/**//* n<=10000灯,初始Off k<=10个特殊位置x1,,xk需要最后是On l<=100种按法,每次可以按连续长为ai的灯,使之off<->on 求最少的步数
一点想法都木有 看了解题报告如此神奇
题目是按连续一段的,首先先转化一下: 用b[0,n]这n+1个数去表示原来的[1,n]个灯的,也即i表示原来的相邻的i, i+1的灯状态, (原来数组[1,n]之外的应该认为为off) 若不同则为b[i]=1,相同为b[i]=0 ---------------------------OMG 这样表示后,若要按连续的一段长为a的灯,如[i,i+a-1] b[]受影响的也只会是头尾,中间的值不会变,即改变b[i],b[i+a],他们flip了
这样转化后,目的就是要对b[],每次flip b[i],b[i+a],使之最后为0 这里就可以k次优先级bfs了 ---------------------------OMG w[i,j]表示使x[i],x[j]flip为0的最小代价 bfs时,起初d[x[i]] = 0,然后用优先级bfs,每次更新s-a[j], s+a[j],是为栈顶 这里有传递性~~~~,神奇的地方 ---------------------------OMG 如使得1-5flip,但只有长度为2的,就可以1-3 ,3-5,中间的3会被抵消掉的!!!!!
最后再mask dp 有k位 dp[mask]表示使b[]中的这些x[i]变为0的最小代价 dp[0] = 0 枚举mask中的0位,扩展~~~
代码看了watashi的 */ #include<cstdio> #include<cstring> #include<set> #include<map> #include<iostream> #include<queue> #include<algorithm>
using namespace std;
const int MAXN = 10086; const int INF = 0x3f3f3f3f;
int dp[1<<20], w[20][20]; int d[MAXN]; int x[20], a[100];
inline int rightZeroBit(int mask) { for (int i = 0; ; i ++) { if ( (mask & (1<<i)) == 0 ){ return i; } } return -1; }
int main() { //freopen("in", "r", stdin); int n, k, l; for (; ~scanf("%d%d%d", &n, &k, &l); ) { for (int i = 0; i < k; i++) { scanf("%d", &x[i]); } sort(x, x+k); k = unique(x, x+k) - x; for (int i = 0; i < l; i ++) { scanf("%d", &a[i]); } sort(a, a+l); l = unique(a, a+l) - a;
set<int> iset; for (int i = 0; i < k; i++) { pair<set<int>::iterator, bool > p; p = iset.insert(x[i]-1); if (!p.second) { iset.erase(p.first); } p = iset.insert(x[i]); if (!p.second) { iset.erase(p.first); } } k = copy(iset.begin(), iset.end(), x) - x;//Good!!!
//cout <<l <<" "<< k <<endl;
for (int i = 0; i < k ;i ++) { fill(d, d+n+1, INF); d[x[i]] = 0; priority_queue<pair<int,int> > pq; pq.push(make_pair(0, x[i])); while(!pq.empty()) { int s = pq.top().second; int t = -pq.top().first; pq.pop(); if (d[s] != t) { continue; } for (int j = 0; j < l ; j ++) { if (s - a[j] >= 0 && d[s-a[j]] > t + 1) { d[s-a[j]] = t + 1; pq.push(make_pair(-d[s-a[j]], s-a[j])); } if (s + a[j] <= n && d[s+a[j]] > t + 1) { d[s+a[j]] = t + 1; pq.push(make_pair(-d[s+a[j]], s+a[j])); } } } for (int j = 0; j < k ;j++) { w[i][j] = d[x[j]]; } }
fill(dp, dp+(1<<k), INF); dp[0] = 0; for (int mask = 0 ; mask < (1<<k); mask++ ) { int u = rightZeroBit(mask); if (u >= k ){ continue; } //cout<<mask<<" "<<dp[mask]<<endl; for (int v = 0; v < k; v++ ) { if ( (mask&(1<<v)) == 0) { int _mask = mask ^ (1<<u) ^ (1<<v); dp[_mask] = min(dp[_mask], dp[mask] + w[u][v]); } } } printf("%d\n", dp[(1<<k)-1] == INF ? -1 : dp[(1<<k)-1]); } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|