測試「20201104測試總結」
阿新 • • 發佈:2020-11-04
搜尋大賽。
T1
令 \(\mathrm{dp}(a,b,x,y)\) 表示用了 \(a\) 個白棋,\(b\) 個黑棋,所得到的序列的所有後綴中白棋最多比黑棋多 \(x\) 個,黑棋最多比白棋多 \(y\) 個的方案數。
若放白棋,有:
\[\mathrm{dp}(a,b,x,y)=\mathrm{dp}(a+1,b,x+1,\max(0,y-1)),x<k,a<n \]若放黑棋,有:
\[\mathrm{dp}(a,b,x,y)=\mathrm{dp}(a,b+1,\max(0,x-1),y+1),y<k,b<m \]考試的時候有點昏,想到的是把字尾中兩種棋子最大的差放進狀態中,結果沒有想出轉移方程,還是打了暴力。
\(\text{Code}:\)
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #define INF 0x3f3f3f3f using namespace std; typedef long long lxl; const int maxn=155; const lxl mod=1e9+7; template <typename T> inline void read(T &x) { x=0;T f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } int n,m,k; int f[maxn][maxn][25][25]; int dp(int a,int b,int x,int y) { if(a==n&&b==m) return 1; if(~f[a][b][x][y]) return f[a][b][x][y]; int res=0; if(a<n&&x<k) (res+=dp(a+1,b,x+1,max(0,y-1)))%=mod; if(b<m&&y<k) (res+=dp(a,b+1,max(0,x-1),y+1))%=mod; return f[a][b][x][y]=res; } int main() { #ifndef ONLINE_JUDGE freopen("chess.in","r",stdin); freopen("chess.out","w",stdout); #endif read(n),read(m),read(k); memset(f,-1,sizeof(f)); printf("%d\n",dp(0,0,0,0)); return 0; }
T2
記憶化搜尋。
毫無頭緒,打了暴力。
\(\text{Code}:\)
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #define INF 0x3f3f3f3f using namespace std; typedef long long lxl; const int maxn=2001; template <typename T> inline void read(T &x) { x=0;T f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } int n,k; int st[maxn],ed[maxn]; int ans=INF; int f[11][maxn][11][11][11]; int dp(int pos,int now,int a,int b,int c) { if(~f[pos][now][a][b][c]) return f[pos][now][a][b][c]; int res=INF; // 下一個人 if(a) res=min(res,dp(a,now,0,b,c)+abs(a-pos)+1); if(b) res=min(res,dp(b,now,a,0,c)+abs(b-pos)+1); if(c) res=min(res,dp(c,now,a,b,0)+abs(c-pos)+1); if(now>n) { if(!a&&!b&&!c) return 0; return f[pos][now][a][b][c]=res; } if(a&&b&&c) // 先接下一個人,再下一個人 { res=min(res,dp(ed[now],now+1,a,b,c)+abs(pos-st[now])+abs(st[now]-ed[now])+2); res=min(res,dp(a,now+1,ed[now],b,c)+abs(pos-st[now])+abs(a-st[now])+2); res=min(res,dp(b,now+1,a,ed[now],c)+abs(pos-st[now])+abs(b-st[now])+2); res=min(res,dp(c,now+1,a,b,ed[now])+abs(pos-st[now])+abs(c-st[now])+2); } else if(!a) // 直接接下一個人 res=min(res,dp(st[now],now+1,ed[now],b,c)+abs(pos-st[now])+1); else if(!b) res=min(res,dp(st[now],now+1,a,ed[now],c)+abs(pos-st[now])+1); else res=min(res,dp(st[now],now+1,a,b,ed[now])+abs(pos-st[now])+1); return f[pos][now][a][b][c]=res; } int main() { #ifndef ONLINE_JUDGE freopen("taxi.in","r",stdin); freopen("taxi.out","w",stdout); #endif read(n),read(k); for(int i=1;i<=n;++i) read(st[i]),read(ed[i]); memset(f,-1,sizeof(f)); printf("%d\n",dp(1,1,0,0,0)); return 0; }
T3
折半搜尋。
分別搜出前後兩部分能組成哪些數,再二分查詢最大能組成哪個數。
\(\text{Code}:\)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <set>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=1e6+5;
template <typename T>
inline void read(T &x)
{
x=0;T f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
x*=f;
}
int n,m,a[45];
set<int> s[2];
int ans;
void dfs(int x,int l,int r)
{
if(l>r) return s[r==n].insert(x),ans=max(ans,x),void();
dfs((x+a[l])%m,l+1,r);
dfs(x,l+1,r);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("stone.in","r",stdin);
freopen("stone.out","w",stdout);
#endif
read(n),read(m);
for(int i=1;i<=n;++i) read(a[i]),a[i]%=m;
dfs(0,1,n/2);
dfs(0,n/2+1,n);
for(set<int>::iterator it=s[0].begin();it!=s[0].end();++it)
{
ans=max(ans,(*it+*(--s[1].upper_bound(m-*it)))%m);
ans=max(ans,(*it+*(--s[1].upper_bound(2*m-*it)))%m);
}
printf("%d\n",ans);
return 0;
}
T4
神仙網路流。
將每個導彈能打到的點串起來,然後最小割。
\(\text{Code}:\)
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=55,maxm=2e5+5;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline void read(T &x)
{
x=0;T f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
x*=f;
}
struct edge
{
int u,v,cp,next;
edge(int u,int v,int cp,int next)
:u(u),v(v),cp(cp),next(next){}
edge(){}
}e[maxm<<1];
int head[maxn*maxn<<1],ecnt;
inline void add(int u,int v,int cp)
{
e[ecnt]=edge(u,v,cp,head[u]);
head[u]=ecnt++;
e[ecnt]=edge(v,u,0,head[v]);
head[v]=ecnt++;
}
int n,m;
int wy[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int G[maxn][maxn];
int s,t;
int d[maxn*maxn<<1],gap[maxn*maxn<<1],nxt[maxn*maxn<<1];
inline void bfs()
{
queue<int> q;
memset(d,0,sizeof(d));
memset(gap,0,sizeof(gap));
++gap[d[t]=1];
q.push(t);
while(!q.empty())
{
int u=q.front();q.pop();
nxt[u]=head[u];
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(d[v]) continue;
++gap[d[v]=d[u]+1];
q.push(v);
}
}
}
int ISAP(int u,int flow)
{
if(u==t||!flow) return flow;
int rest=flow;
for(int &i=nxt[u];~i;i=e[i].next)
{
int v=e[i].v;
if(!e[i].cp||d[v]+1!=d[u]) continue;
int k=ISAP(v,min(e[i].cp,rest));
if(!k) continue;
e[i].cp-=k;
e[i^1].cp+=k;
rest-=k;
if(!rest) return flow;
}
nxt[u]=head[u];
if(!--gap[d[u]]) d[s]=t+1;
++gap[++d[u]];
return flow-rest;
}
inline int pos(int x,int y) {return (x-1)*m+y;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("missile.in","r",stdin);
freopen("missile.out","w",stdout);
#endif
read(n),read(m);
memset(head,-1,sizeof(head));
s=1;t=n*m*2+2;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
read(G[i][j]);
add(pos(i,j)<<1,pos(i,j)<<1|1,INF);
}
int maxflow=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
if(G[i][j]>=0) continue;
int type=abs(G[i][j])-1;
if(type<=1) add(s,pos(i,j)<<1,INF);
else add(pos(i,j)<<1|1,t,INF);
int px=i,py=j,x=px+wy[type][0],y=py+wy[type][1];
if(x>n||x<1||y>m||y<1) continue;
int Max=0;
while(x<=n&&y<=m&&x>=1&&y>=1)
{
Max=max(Max,max(0,G[x][y]));
x+=wy[type][0];y+=wy[type][1];
}
x=px+wy[type][0],y=py+wy[type][1];
while(x<=n&&y<=m&&x>=1&&y>=1)
{
if(type<=1) add(pos(px,py)<<1,pos(x,y)<<1,Max-max(0,G[px][py]));
else add(pos(x,y)<<1|1,pos(px,py)<<1|1,Max-max(0,G[px][py]));
px+=wy[type][0];py+=wy[type][1];
x+=wy[type][0];y+=wy[type][1];
}
maxflow+=Max;
}
bfs();
while(d[s]<=t)
maxflow-=ISAP(s,1<<30);
printf("%d\n",maxflow);
return 0;
}