文章前食用:本蒟蒻有一个坏习惯 会写read 然后就是max min abs会手打QAQ(所以当然不可能手打快排)当然你们可以理解学习我的写法(这种写法纯属偷懒)
A CSU1460
思路:本题思路两种
思路1:用DFS 记忆化搜索 不走相同的路 看看能不能到终点
思路2:图论 这要是放在图论算是水题了 重点:把1000距离以内的当做一条边
然后用Floyd 去判断两点之间有没有路
下面是你们喜欢的代码QAQ
DFS
#include <bits/stdc++.h>
#define f(i,j,n) for(register int i=j;i<=n;i++)
using namespace std;
typedef long long ll;
inline ll read() {
ll x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch)) {
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch-48),ch=getchar();
return x*f;
}
int n;
int xa,ya,xb,yb;
struct node {
int x,y;
} a[100+5];
bool vis[100+5];
bool flag=false;
inline ll Abs(ll x) {
return x>0?x:-x;
}
inline void dfs(int x,int y) {
if(Abs(xb-x)+Abs(yb-y)<=1000) {
flag=true;
return;
}
f(i,1,n)
if(Abs(a[i].x-x)+Abs(a[i].y-y)<=1000 and!vis[i])
vis[i]=true,dfs(a[i].x,a[i].y);
}
int main() {
int t=read();
while(t--) {
flag=false;
memset(a,0,sizeof(a));
memset(vis,false,sizeof(vis));
n=read();
xa=read(),ya=read();
f(i,1,n) a[i].x=read(),a[i].y=read();
xb=read(),yb=read();
dfs(xa,ya);
flag?puts("win"):puts("lose");
}
return 0;
}
Floyd
#include<bits/stdc++.h>
#define f(i,j,n) for(register int i=j;i<=n;i++)
using namespace std;
typedef long long ll;
inline ll read() {
ll x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch)) {
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch-48),ch=getchar();
return x*f;
}
struct node {
int x,y;
} a[100+5];
bool f[100+5][100+5];
inline int Abs(int x) {
return x>0?x:-x;
}
inline int qaq(node x,node y) {
return Abs(x.x-y.x)+Abs(x.y-y.y);
}
int main() {
int t=read();
while(t--) {
memset(a,0,sizeof(a)),memset(f,false,sizeof(f));
int n=read()+2;
f(i,1,n) a[i].x=read(),a[i].y=read();
f(i,1,n-1) f(j,i+1,n) if(qaq(a[i],a[j])<=1000) f[i][j]=f[j][i]=true;
f(k,1,n) f(i,1,n) if(i!=k) f(j,1,n) if(f[i][k] and f[k][j]) f[i][j]=true;
if(f[1][n]) puts("win");
else puts("lose");
}
return 0;
}
B HDU4499改编
思路:
(1)A和B在棋盘的同一行或同一列中;
(2)A和B之间有且只有一个其它棋子。
判断当前行和当前列能不能放棋子QAQ 码量有点大 可以复制一大段稍微改一下QAQ
DFS
#include <bits/stdc++.h>
#define f(i,j,n) for(register int i=j;i<=n;i++)
using namespace std;
typedef long long ll;
using namespace std;
inline ll read() {
ll x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch)) {
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch-48),ch=getchar();
return x*f;
}
int ans,n,m,q,T;
int vis[1<<4][1<<4];
inline int Max(int x,int y) {
return x>y?x:y;
}
inline bool check(int a,int b) {
register int flat=0,i,j;
for(i=a-1; i>=1; i--) if(vis[i][b]) break;
for(j=i-1; j>=1; j--) if(vis[j][b]==1) break;
else if(vis[j][b]==2) {
flat=1;
break;
}
if(flat) return false;
for(i=b-1; i>=1; i--) if(vis[a][i]) break;
for(j=i-1; j>=1; j--) if(vis[a][j]==1) break;
else if(vis[a][j]==2) {
flat=1;
break;
}
if(flat) return false;
return true;
}
inline void dfs(int x,int y,int cnt) {
if(x==n and y==m+1) {
ans=Max(ans,cnt);
return;
}
if(y==m+1) {
dfs(x+1,1,cnt);
return;
}
if(vis[x][y]) {
dfs(x,y+1,cnt);
return;
}
dfs(x,y+1,cnt);
if(check(x,y)) vis[x][y]=2,dfs(x,y+1,cnt+1),vis[x][y]=0;
}
int main() {
T=read();
while(T--) {
ans=0;
memset(vis,false,sizeof(vis));
n=read(),m=read(),q=read();
f(i,1,q) {
int x=read(),y=read();
vis[x+1][y+1]=1;
}
dfs(1,1,0);
cout<<ans<<endl;
}
return 0;
}
C Michigan Invitational Programming Competition October 9,2011
思路:从最大的面积开始 如果满足条件更新 加上check 每次搜索时带上一个check函数来判断范围内有没有蓝点(不应该判断区间 应该从点的下标开始) 由此 应该把红点 放在a数组 蓝点放在b数组 做b的循环 因为n<=20 所以b一定<=20 所以时间复杂度不高 但是如果判断区间 应该就是每次2000*2000=40000000 也就是说 每个点都会超时(除非数据水) 见代码QAQ
DFS
#include <bits/stdc++.h>
#define f(i,j,n) for(register int i=j;i<=n;i++)
using namespace std;
typedef long long ll;
typedef unsigned int uint;
const int inf=0x7f7f7f7f;
inline ll read() {
ll x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch)) {
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch-48),ch=getchar();
return x*f;
}
int n,cnt1,cnt2,ans=inf;
struct node {
int x,y;
};
node a[1<<6],b[1<<6];
template<typename t>inline t Max(t x,t y) {
return x>y?x:y;
}
template<typename t>inline t Min(t x,t y) {
return x<y?x:y;
}
inline bool check(int x,int xx,int y,int yy) {
f(i,0,cnt2-1) if(b[i].x<=x and b[i].x>=xx and b[i].y<=y and b[i].y>=yy) return false;
return true;
}
inline void dfs(int t,int pre,int xmax,int xmin,int ymax,int ymin) {
if(t>=(cnt1/2)) {
if(check(xmax,xmin,ymax,ymin)) ans=Min(ans,(xmax-xmin)*(ymax-ymin));
return;
}
f(i,pre+1,cnt1-1) dfs(t+1,i,Max(a[i].x,xmax),Min(xmin,a[i].x),Max(ymax,a[i].y),Min(ymin,a[i].y));
}
int main() {
n=read(),ans=inf,cnt1=0,cnt2=0;
f(i,1,n) {
int x=read(),y=read(),z=read();
if(z==0)a[cnt1].x=x,a[cnt1].y=y,cnt1++;
else b[cnt2].x=x,b[cnt2].y=y,cnt2++;
}
dfs(0,-1,-inf,inf,-inf,inf);
ans==inf?puts("-1"):printf("%d\n",ans);
return 0;
}
D
思路:奇偶性剪枝??QAQ tql %%%%@hjf 真的太巨了 能减掉一堆无用的状态QAQ 所以不难得出几种剪枝QAQ{1 时间不够的提前减掉 2 奇偶性剪枝 3 在搜索前特判(eg: 3 3 4
SXX
.XX
X.D
上面的例子满足m*n-wall=t,确实不能到达,但不能找到合理的解释......
)}
脑补一下 temp&1 == temp%2==1 QAQ
DFS 的参数//当前位置坐标(x,y),到目前位置消耗时间
#include <bits/stdc++.h>
#define f(i,j,n) for(register int i=j;i<=n;i++)
using namespace std;
typedef long long ll;
inline ll read() {
ll x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch)) {
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch-48),ch=getchar();
return x*f;
}
char a[10][10];
int n,m,t;
int sx,sy,ex,ey;
bool flag;
int dir[4][2]= {0,1,1,0,0,-1,-1,0};
int abs(int x) {
return x<0?-x:x;
}
void DFS(int x,int y,int time) {
if(x<0 or x>=n or y<0 or y>=m) return;
if(x==ex and y==ey and time==t) {
flag=true;
return ;
}
if(flag) return;
int temp=(t-time)-(abs(x-ex)+abs(y-ey));
if(temp<0 or temp&1) return;
f(i,0,3) {
int xx=x+dir[i][0],yy=y+dir[i][1];
if(a[xx][yy]!='X') {
a[xx][yy]='X',DFS(xx,yy,time+1),a[xx][yy]='.';
if(flag) return ;
}
}
}
int main() {
while(1) {
n=read(),m=read(),t=read();
if(!n and !m and !t) return 0;
int wall=0;
f(i,0,n-1)
f(j,0,m-1) {
cin>>a[i][j];
if(a[i][j]=='S') sx=i,sy=j;
if(a[i][j]=='D') ex=i,ey=j;
if(a[i][j]=='X') wall++;
}
if(n*m-wall<=t) {
puts("NO");
continue;
}
flag=false,a[sx][sy]='X';
DFS(sx,sy,0);
flag?puts("YES"):puts("NO");
}
}