题解:
没啥好说的\(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;
}
题解:
不知道为什么,突然就想试试新学的方法飘逸一波,不用常规的写法\(......\)
用\(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]);
}
题解:
直接上出题人的博客网址,本题实际上就是带权可持久化并查集
\(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:我的代码怎么现在越写越长了\(......\))