2018.10.10 练习赛 状态压缩专练(T4-T5)

T4 Tourism

题解:

\(F[p][s]\)表示讨论到p号点,根到p路径(不包含p)上的点的服务状态为s的最小费用。

\(S\)\(3\)进制数,\(0\)表示\(p\)自己服务自己,\(1\)表示\(p\)没有被服务到,\(2\)表示被其它点服务,这里的状态记录的是父亲

一直到根这条链上的,不超过\(10\)层,所以最多是\(3^{10}\)

\(code\):

//待补

T2 LED

题解:

\(bfs\)算出置反一段区间的最小代价,状压更新

\(code:\)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctype.h>
#include<queue>
#define inf 1e9+9
using namespace std;

int t,n,k,l,cnt,tot;
int a[10005],g[10005],pos[10005],c[10005],f[1<<21];
queue<int>q;
int main()
{
//	freopen("1.txt","w",stdout);
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d",&n,&k,&l);cnt=0;
		for(int i=1;i<=k;i++) scanf("%d",&a[i]);
		for(int i=1;i<=l;i++) scanf("%d",&c[i]),q.push(c[i]);
		sort(a+1,a+k+1);
        k=unique(a+1,a+k+1)-(a+1);
        a[0]=-1,a[k+1]=n+2;
        
		for(int i=1; i<=k; i++) {
        if(a[i]!=a[i-1]+1) pos[cnt++]=a[i];
        if(a[i]!=a[i+1]-1) pos[cnt++]=a[i]+1;
        }tot=(1<<cnt)-1;
		
//		for(int i=0;i<cnt;i++) printf("%d:%d\n",i+1,pos[i]);
		sort(pos,pos+cnt);
		for(int i=1;i<=n;i++) g[i]=inf;
		for(int i=1;i<=l;i++) g[c[i]]=1;
//		for(int i=0;i<cnt;i++) printf("%d:%d\n",i+1,pos[i]);
		
		while(!q.empty()) {
            int x=q.front();
            q.pop();
            
            for(int i=1; i<=l; i++) {
                if(x+c[i]<=n&&g[x+c[i]]==inf) {
                    g[x+c[i]]=g[x]+1;
                    q.push(x+c[i]);
                }
                if(x-c[i]>=1&&g[x-c[i]]==inf) {
                    g[x-c[i]]=g[x]+1;
                    q.push(x-c[i]);
                }
            }
        }
        
//		for(int i=1;i<=n;i++) printf("%d\n",g[i]);
		
		for(int s=1;s<=tot;s++)
		{
			f[s]=inf;int i;
			for(i=0;i<cnt;i++)
			if(s>>i&1) break;
			for(int j=i+1;j<cnt;j++) if(s>>j&1)
			f[s]=min(f[s],f[s^(1<<i)^(1<<j)]+g[pos[j]-pos[i]]);
		}
//		for(int i=0;i<cnt;i++) printf("%d:%d\n",i+1,pos[i]);
		if(f[tot]==inf) puts("-1");
		else printf("%d\n",f[tot]);
	}
}
posted @ 2018-10-10 23:46  Katoumegumi  阅读(95)  评论(0编辑  收藏  举报
返回顶部