2018.10.07 练习赛

T1 幻象迷宫

题解:

没啥好说的\(dfs\)

\(code\):

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<ctype.h>
#include<queue>
#include<string.h>
#include<vector>
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
//	return getchar();
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
	char tt;
	while(!isdigit(tt=gc()));x=tt-'0';
	while(isdigit(tt=gc())) x=x*10+tt-'0';
}

int n,m;
const int dx[4]={0,1,-1,0};
const int dy[4]={1,0,0,-1};
char a[1505][1505];
bool flag;
int book[1505][1505][3],startx,starty;

void dfs(int x,int y,int qx,int qy)
{
	if(book[x][y][0]&&(book[x][y][1]!=qx||book[x][y][2]!=qy)) flag=1;
    if(book[x][y][0]||flag) return;
    book[x][y][1]=qx,book[x][y][2]=qy,book[x][y][0]=1;
    for(int i=0;i<4;i++)
    {
        int nxtx=(x+dx[i]+n)%n,nxty=(y+dy[i]+m)%m;
        if(a[nxtx][nxty]!='#')
        dfs(nxtx,nxty,qx+dx[i],qy+dy[i]);
    }
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		flag=0;
		memset(book,0,sizeof(book));
		for(int i=0;i<n;i++)
		{
			scanf("\n");
			for(int j=0;j<m;j++)
			{
				scanf("%c",&a[i][j]);
				if(a[i][j]=='S') startx=i,starty=j;
			}
		}
		dfs(startx,starty,startx,starty);
		if(flag) puts("Yes");
		else puts("No");
	}
	return 0;
}

T2 观铟桥商业街

题解:

不知道为什么,突然就想试试新学的方法飘逸一波,不用常规的写法\(......\)

\(W[i][S]\)表示第i个店买完\(S\)这个集合的东西需要多少钱,原地高维前缀和\(O(N*2^M)\)预处理,然后\(F[S]\)表示买完这个集合的最小代价,转换很简单\(......\)枚举一个集合,从它的补集的子集转移就行了,不用考虑重复,因为这种情况一定会被更优的更新掉.

\(code:\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<ctype.h>
#include<queue>
#include<string.h>
#include<vector>
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
	return getchar();
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
	char tt;
	while(!isdigit(tt=gc()));x=tt-'0';
	while(isdigit(tt=gc())) x=x*10+tt-'0';
}

int n,m,tot;
int a[105],w[105][1<<11];
ll f[1<<11];
int main()
{
	read(n),read(m);
	for(int i=1;i<=n;i++) read(a[i]);
	for(int i=1;i<=n;i++)
	{ 
		for(int j=1;j<=m;j++)
		read(w[i][1<<(j-1)]);
	} tot=(1<<m)-1;
	
	for(int i=1;i<=n;i++)// O(N*M*2^M)
	for(int j=0;j<=m;j++)
	for(int s=0;s<=tot;s++)
	if((s>>j)&1) w[i][s]+=w[i][s^(1<<j)];
	
	memset(f,127,sizeof(f));
	f[0]=0;
	
	for(int i=1;i<=n;i++)//O(N*3^N)? 
	for(int s=0;s<=tot;s++)
	{
		int sp=tot^s;
		for(int t=sp;;t=(t-1)&sp)
		{
			f[s|t]=min(f[s|t],f[t]+w[i][s]+a[i]);
			if(!t) break;
		}
	}
	printf("%lld",f[tot]);
}

T3 英勇赛尔,智慧童年!

题解:

直接上出题人的博客网址,本题实际上就是带权可持久化并查集

点这里

\(code:\)

#include<cstdio> 
#include<iostream> 
#include<algorithm> 
#include<ctype.h> 
#include<queue> 
#include<string.h> 
#include<vector> 
using namespace std; 

char buf[1<<20],*p1,*p2; 
inline char gc() 
{ 
//    return getchar(); 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; 
} 

template<typename T> 
inline void read(T &x) 
{ 
    char tt; 
    while(!isdigit(tt=gc()));x=tt-'0'; 
    while(isdigit(tt=gc())) x=x*10+tt-'0'; 
} 

char pbuf[1<<20],*pp=pbuf;
inline void push(const char c)
{
    if(pp-pbuf==(1<<20)) fwrite(pbuf,1,(1<<20),stdout),pp=pbuf;
    *pp++=c;
}

template<typename T>
inline void write(T x)
{
    static int sta[35];
    int top=0;
    if(x<0) push('-'),x=-x;
    do {
        sta[top++]=x%10,x/=10;
    } while(x);
    while(top) push(sta[--top]+'0');
    push('\n');
}

struct node{ 
    int opt,x,y; 
    inline node(int a=0,int b=0,int c=0) 
    { 
        opt=a; 
        x=b; 
        y=c; 
    } 
}a[1000005]; 

struct back_{ 
    int fa,len; 
    inline back_(int a=0,int b=0) 
    { 
        fa=a; 
        len=b; 
    } 
}; 

inline int sub(int a,int b) 
{ 
    return ((a%5-b%5+5)%5+5)%5;
} 
int n,m,now; 
int ans[1000005]; 
int fa[800005],dis[800005],sz[800005]; 
int s[1000005],top,last[1000005]; 
vector<int>G[1000005]; 

back_ getfa(int x)
{
	int sum=0;
	while(fa[x]!=x)
	{
		sum+=dis[x];
		x=fa[x];
	}
	return back_(x,sum);
}

void cachu()
{
	int x=s[top--];
	if(x==-1) return;
	fa[x]=x;dis[x]=0;sz[fa[x]]-=sz[x];
}

bool merge(int x,int y,int len) 
{ 
	back_ tmpx=getfa(x),tmpy=getfa(y);
	int fx=tmpx.fa,disx=tmpx.len,fy=tmpy.fa,disy=tmpy.len;
	if(fx==fy)
	{
//		printf("%d %d %d %d %d\n",x,y,fx,fy,sub(disx,disy));
		if(sub(disx,disy)!=len) return 0;
		else s[++top]=-1;
	}
	else
	{
		if(sz[fx]>sz[fy])
		{
			fa[fy]=fx;
			sz[fx]+=sz[fy];
			dis[fy]=disx-disy-len;
			s[++top]=fy;
//			printf("%d %d %d\n",fa[fy],sz[fx],dis[fy]);
		}
		else
		{
			fa[fx]=fy;
			sz[fy]+=sz[fx];
			dis[fx]=disy-disx+len;
			s[++top]=fx;
//			printf("%d %d %d\n",fa[fx],sz[fy],dis[fx]);	
		}
	}
	return 1;
} 

void dfs(int x,int pre) 
{ 
    if(!x) 
    { 
        for(int i=G[x].size()-1;i>=0;i--) dfs(G[x][i],x); 
        return; 
    }
    last[x]=pre;
    int opt=a[x].opt,tmpx=a[x].x,tmpy=a[x].y; 
    if(!ans[pre]) ans[x]=0; 
    else
	{
		if(opt==3) 
    	{ 
        	ans[x]=ans[pre]; 
        	if(ans[x]) s[++top]=-1;         
    	} 
   		else 
    	{ 
        	if(opt==1) ans[x]=merge(tmpx,tmpy,2); 
        	if(opt==2) ans[x]=merge(tmpx,tmpy,4); 
    	}
	}
    for(int i=G[x].size()-1;i>=0;i--) dfs(G[x][i],x); 
    if(ans[x]&&ans[pre]) cachu(); 
} 

int main() 
{ 
// 	freopen("saier.in","r",stdin);
    read(n),read(m); 
    for(int i=1;i<=n;i++)  fa[i]=i,sz[i]++; 
    for(int i=1;i<=m;i++) 
    { 
        int t,x,y; 
        read(t); 
        if(t==1||t==2) 
        { 
            read(x),read(y); 
            a[i]=node(t,x,y); 
            G[now].push_back(i); 
            now=i; 
        } 
        else 
        { 
            read(x); 
            now-=x; 
            a[i]=node(t,x); 
            G[now].push_back(i); 
            now=i; 
        } 
    } 
    ans[0]=1; 
    dfs(0,0);
    for(int i=1;i<=m;i++)
    if(ans[i]) push('t'),push('r'),push('u'),push('e'),push('\n');
    else push('f'),push('a'),push('l'),push('s'),push('e'),push('\n');
    fwrite(pbuf,1,pp-pbuf,stdout);
} 

(ps:我的代码怎么现在越写越长了\(......\))

posted @ 2018-10-07 23:53  Katoumegumi  阅读(65)  评论(0编辑  收藏  举报
返回顶部