程序返回可行解的个数,最好使用dfs
因为每行只能放一个棋子,所以每一行的状态只需用一个数表示,记录棋子的位置
整个棋盘的状态用一个一维数组表示
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int pos[10];
string h[10];
int n,k;
ll solve(int hang,int res_k){
ll res=0;
if(res_k==0) return 1;
if(hang>=n) return 0;
res+=solve(hang+1,res_k);
// cout<
for( int i=0;i<n;i++){
if(h[hang][i]=='.') continue;
else {
for( int j=0;j<hang;j++)
if(pos[j]==i) goto endd;
pos[hang]=i;
res+=solve(hang+1,res_k-1);
pos[hang]=-1;
endd:;
}
}
return res;
}
int main(){
while(cin>>n>>k){
// if(n==0||k==0) {
// cout<<0<
// continue;
// }
if(n==-1&&k==-1) break;
for( int i=0;i<n;i++){
cin>>h[i];
}
memset(pos,-1,sizeof(pos));
cout<<solve(0,k)<<endl;
}
return 0;
}
直接写
#include
#include
#include
using namespace std;
const int N=110;
int a,b;
int vis[1000100];
int step[1000100];
int bfs(){
queue<int>q;
vis[a]=1;
q.push(a);
while(!q.empty()){
int now=q.front();
q.pop();
if(now==b) break;
if(now>5e5+2) continue;
if(vis[now*2]==0){
vis[now*2]=1;
step[now*2]=step[now]+1;
q.push(now*2);
}
if(now-1>=0&&vis[now-1]==0){
vis[now-1]=1;
step[now-1]=step[now]+1;
q.push(now-1);
}
if(vis[now+1]==0){
vis[now+1]=1;
step[now+1]=step[now]+1;
q.push(now+1);
}
}
return step[b];
}
int main(){
cin>>a>>b;
cout<<bfs()<<endl;
return 0;
}
用python写的,代码质量不太高
vis={-1};
def dfs(x):
if(x in vis):
return -1;
vis.add(x);
s=str(x);
if(len(s)>100):
return -1;
if(x!=0 and x%n==0):
return x;
res=dfs(x*10);
if(res!=-1) :
return res;
res=dfs(x*10+1);
if(res!=-1):
return res;
return -1;
while(1):
global n
n=int(input());
vis={-1}
if(n==0):
break;
print(dfs(0));
先预处理出所有质数,然后处理出质数之间的状态转移路径。这和状压dp比较相似
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=100100;
vector<int>h[N];
int st[N];//1不是质数0是质数
void get_prime(){
st[1]=1;
for( int i=2;i<=9999;i++){
if(st[i]!=0) continue;
for( int j=i+i;j<=9999;j+=i){
st[j]=1;
}
}
return ;
}
string int_to_string(int x){
string res;
res+=x/1000+'0',x%=1000;
res+=x/100+'0',x%=100;
res+=x/10+'0',x%=10;
res+=x+'0';
return res;
}
int string_to_int(string s){
int res=0;
for( int i=0;i<s.size();i++){
res=res*10+s[i]-'0';
}
return res;
}
void get_path(){
for( int i=1000;i!=9999;i++){
if(st[i]==1) continue;
string s=int_to_string(i);
for( int j=0;j<4;j++){
string ss=s;
for( int k=0;k<10;k++){
if(j==0&&k==0) continue;
ss[j]=k+'0';
int x=string_to_int(ss);
if(x==i) continue;
if(st[x]==0) h[i].push_back(x);
}
}
}
}
int be,en;
int bfs( ){
if(be==en) return 0;
queue<int>q;
q.push(be);
int vis[100100]={};
int step[100100]={};
memset(step,0x3f,sizeof(step));
step[be]=0;
while(!q.empty()){
int now=q.front();
q.pop();
for( int i=0;i<h[now].size();i++){
if(h[now][i]==en) return step[now]+1;
if(vis[h[now][i]]==0){
vis[h[now][i]]=1;
q.push(h[now][i]);
step[h[now][i]]=step[now]+1;
}
}
}
return -1;
}
int main(){
int t;
cin>>t;
get_prime();
get_path();
while(t--){
cin>>be>>en;
int ans=bfs();
if(ans==-1){
cout<<"Impossible"<<endl;
}
else cout<<ans<<endl;
}
return 0;
}
直接模拟
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
string s1,s2,s12;
int n;
int solve(){
int res=0;
string now;
set<string>vis;
while(now!=s12){
if(vis.find(now)!=vis.end()) return -1;
else vis.insert(now);
// cout<
now.clear();
for( int i=0;i<n*2;i++){
if(i%2==0) now+=s2[i/2];
else now+=s1[i/2];
}
// cout<
res++;
s1.clear();
s2.clear();
for( int i=0;i<n;i++) {
s1+=now[i];
}
for( int i=n;i<n+n;i++){
s2+=now[i];
}
}
return res;
}
int main(){
int t;
cin>>t;
for( int tt=1;tt<=t;tt++){
cin>>n>>s1>>s2>>s12;
cout<<tt<<" "<<solve()<<endl;
}
return 0;
}
模拟倒水,用一个数组存储最优解的来源
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=110;
int step[N][N];
pair<int,int> pre[N][N];
int pre_val[N][N];
int a,b,c;
//1.fill1 2.fill2 3.drop1 4.drop2 5.pour1,2 6.pour2,1
pair<int,int> change( pair<int,int>p,int x){
if(x==1) {
p.first=a;
return p;
}
else if(x==2){
p.second=b;
return p;
}
else if(x==3){
p.first=0;
return p;
}
else if(x==4){
p.second=0;
return p;
}
else if(x==5){
int mov=min(b-p.second,p.first);
p.first-=mov;
p.second+=mov;
return p;
}
else if(x==6){
int mov=min(a-p.first,p.second);
p.second-=mov;
p.first+=mov;
return p;
}
}
int bfs( int x,int y){
set<pair<int,int> >vis;
queue<pair<int,int> >q;
q.push(make_pair(x,y));
vis.insert(make_pair(x,y));
while(!q.empty()){
pair<int,int>now=q.front();
q.pop();
if(now.first==c||now.second==c){
a=now.first,b=now.second;
return step[now.first][now.second];
}
for( int i=1;i<=6;i++){
pair<int,int>temp=change(now,i);
if(vis.find(temp)==vis.end()){
step[temp.first][temp.second]=step[now.first][now.second]+1;
vis.insert(temp);
q.push(temp);
pre[temp.first][temp.second]=make_pair(now.first,now.second);
pre_val[temp.first][temp.second]=i;
}
}
}
return -1;
}
int main(){
cin>>a>>b>>c;
int ans=bfs(0,0);
if(ans!=-1){
cout<<ans<<endl;
stack<int>st;
while(a!=0||b!=0){
st.push(pre_val[a][b]);
int aa=pre[a][b].first;
int bb=pre[a][b].second;
a=aa,b=bb;
}
while(!st.empty()){
int t=st.top();
st.pop();
if(t==1){
cout<<"FILL(1)"<<'\n';
}
else if(t==2){
cout<<"FILL(2)"<<'\n';
}
else if(t==3){
cout<<"DROP(1)"<<'\n';
}
else if(t==4){
cout<<"DROP(2)"<<'\n';
}
else if(t==5){
cout<<"POUR(1,2)"<<'\n';
}
else if(t==6){
cout<<"POUR(2,1)"<<'\n';
}
}
}
else cout<<"impossible"<<endl;
return 0;
}
直接写
#include
#include
#include
#include
#include
#include
using namespace std;
const int inf=0x3f3f3f3f,N=510;
int a[10][10],prex[10][10],prey[10][10],vis[10][10];
int mov[4][2]={0,1,0,-1,1,0,-1,0};
int check( pair<int,int> p){
if(vis[p.first][p.second]==1) return 0;
if(p.first<1||p.first>5||p.second<1||p.second>5||a[p.first][p.second]==1) return 0;
return 1;
}
void bfs(){
queue<pair<int,int> > q;
q.push(make_pair(1,1));
vis[1][1]=1;
while(!q.empty()){
pair<int,int> now=q.front();
q.pop();
// cout<
if(now.first==5&&now.second==5) break;
vis[now.first][now.second]=1;
for( int i=0;i<4;i++){
pair<int,int>temp=now;
temp.first+=mov[i][0];
temp.second+=mov[i][1];
if(check(temp)){
prex[temp.first][temp.second]=now.first;
prey[temp.first][temp.second]=now.second;
q.push(temp);
}
}
}
}
int main(){
int n=5;
for( int i=1;i<=n;i++){
for( int j=1;j<=n;j++){
cin>>a[i][j];
}
}
bfs();
int x=5,y=5;
stack<int >ansx;
stack<int >ansy;
while(1){
ansx.push(x-1);
ansy.push(y-1);
int xx=prex[x][y];
int yy=prey[x][y];
x=xx,y=yy;
if(x==1&&y==1) break;
}
ansx.push(0),ansy.push(0);
while(!ansx.empty()){
printf("(%d, %d)\n",ansx.top(),ansy.top());
ansx.pop(),ansy.pop();
}
return 0;
}
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=110;
int n,m;
string h[N];
int vis[N][N];
int mov[8][2]={0,1,0,-1,1,0,1,1,1,-1,-1,-1,-1,0,-1,1};
int check(pair<int,int>p){
if(p.first<0||p.first>=n||p.second<0||p.second>=m) return 0;
if(h[p.first][p.second]=='*'||vis[p.first][p.second]==1) return 0;
return 1;
}
void bfs( int x,int y){
queue<pair<int,int> >q;
q.push(make_pair(x,y));
vis[x][y]=1;
while(!q.empty()){
pair<int,int>now=q.front();
q.pop();
for( int i=0;i<8;i++){
pair<int,int>temp=now;
temp.first+=mov[i][0];
temp.second+=mov[i][1];
if(check(temp)==1){
vis[temp.first][temp.second]=1;
q.push(temp);
}
}
}
}
int main(){
while(cin>>n>>m){
if(n==0&&m==0) break;
memset(vis,0,sizeof(vis));
for( int i=0;i<n;i++){
cin>>h[i];
}
int ans=0;
for( int i=0;i<n;i++){
for( int j=0;j<m;j++){
if(vis[i][j]==0&&h[i][j]=='@'){
bfs(i,j);
ans++;
}
}
}
cout<<ans<<endl;
}
return 0;
}
写一个倒水函数可以减少代码量
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int vis[110][110][110];
int step[110][110][110];
int w[3];
struct p{
int a[3];
};
p pour(int from,int to,p x){
int mov=min(x.a[from],w[to]-x.a[to]);
x.a[from]-=mov;
x.a[to]+=mov;
return x;
}
int check(p now){
int cnt=0;
for( int i=0;i<3;i++){
if(now.a[i]*2==w[0]) cnt++;
}
if(cnt==2) return 1;
else return 0;
}
int bfs( p be){
queue<p>q;
q.push(be);
vis[be.a[0]][be.a[1]][be.a[2]]=1;
while(!q.empty()){
p now=q.front();
q.pop();
if(check(now)) return step[now.a[0]][now.a[1]][now.a[2]];
for( int i=0;i<3;i++){
for( int j=0;j<3;j++){
if(i==j) continue;
p temp=pour(i,j,now);
if(vis[temp.a[0]][temp.a[1]][temp.a[2]]==0){
vis[temp.a[0]][temp.a[1]][temp.a[2]]=1;
step[temp.a[0]][temp.a[1]][temp.a[2]]=step[now.a[0]][now.a[1]][now.a[2]]+1;
q.push(temp);
}
}
}
}
return -1;
}
int main(){
while(cin>>w[0]>>w[1]>>w[2]){
if(w[0]==0&&w[1]==0&&w[2]==0) break;
memset(vis,0,sizeof(vis));
memset(step,0,sizeof(step));
p now;
now.a[0]=w[0],now.a[1]=0,now.a[2]=0;
int ans=bfs(now);
if(ans==-1) cout<<"NO"<<endl;
else cout<<ans<<endl;
}
return 0;
}
对M和Y分别进行bfs,用两个数组记录距离,然后遍历每个@的距离,取最小值
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=210,inf=0x3f3f3f3f;
int n,m;
string h[N];
int vis[N][N];
int step[N][N][2];
int mov[4][2]={0,1,0,-1,1,0,-1,0};
int check(pair<int,int> p){
if(p.first<0||p.first>=n||p.second<0||p.second>=m) return 0;
if(vis[p.first][p.second]==1||h[p.first][p.second]=='#') return 0;
return 1;
}
void bfs(int x,int y,int flag){
memset(vis,0,sizeof(vis));
queue<pair<int,int> >q;
q.push(make_pair(x,y));
vis[x][y]=1;
while(!q.empty()){
pair<int,int>now=q.front();
q.pop();
for( int i=0;i<4;i++){
pair<int,int>temp=now;
temp.first+=mov[i][0];
temp.second+=mov[i][1];
if(check(temp)){
vis[temp.first][temp.second]=1;
step[temp.first][temp.second][flag]=step[now.first][now.second][flag]+1;
q.push(temp);
}
}
}
}
int main(){
while(cin>>n>>m){
memset(step,0,sizeof(step));
for( int i=0;i<n;i++){
cin>>h[i];
for( int j=0;j<m;j++){
if(h[i][j]=='@'){
step[i][j][0]=step[i][j][1]=inf;
}
}
}
for( int i=0;i<n;i++){
for( int j=0;j<m;j++){
if(h[i][j]=='Y'){
bfs(i,j,0);
}
if(h[i][j]=='M'){
bfs(i,j,1);
}
}
}
int ans=inf;
for( int i=0;i<n;i++){
for( int j=0;j<m;j++){
if(h[i][j]=='@'){
ans=min(step[i][j][0]+step[i][j][1],ans);
}
}
}
cout<<ans*11<<endl;
}
return 0;
}
本题需要对每个状态进行状态压缩,压缩的方法是将两位数当成一个字符,存在一个string中,判重数组直接用set代替
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define x first
#define y second
#define hash hashh
const int N=110;
int w[10][10];
int now[10][10];
string ans_s;
string hash(){
string res;
for( int i=0;i<4;i++){
for( int j=0;j<=7;j++){
res+=now[i][j];
}
}
return res;
}
void rehash(string &s){
memset(now,0,sizeof(now));
for( int i=0;i<4;i++){
for( int j=0;j<=7;j++){
now[i][j]=s[i*8+j];
}
}
}
pair<int,int> find(int a){
for( int i=0;i<4;i++){
for( int j=0;j<=7;j++){
if(now[i][j]==a){
return make_pair(i,j);
}
}
}
return make_pair(-1,-1);
}
void debugg(){
for( int i=0;i<4;i++){
for( int j=0;j<=7;j++){
cout<<now[i][j]<<" ";
}
cout<<endl;
}
cout<<endl<<endl;
}
void init(){
for( int i=0;i<4;i++){
for( int j=0;j<=7;j++){
now[i][j]=w[i][j];
}
}
for( int i=0;i<4;i++){
pair<int,int>p=find((i+1)*10+1);
now[i][0]=(i+1)*10+1;
now[p.x][p.y]=0;
}
}
string get_ans_s(){
int w2[10][10];
string res;
for( int i=0;i<4;i++){
for( int j=0;j<=7;j++){
if(j==7) w2[i][j]=0;
else w2[i][j]=(((i+1)*10)+j+1);
res+=(char)w2[i][j];
}
}
return res;
}
int check(string &s){
return s==ans_s;
return 1;
}
int bfs( ){
queue<string>q;
set<string>vis;
map<string,int>mp;
init();
ans_s=get_ans_s();
// debugg();
string s=hash();
q.push(s);
vis.insert(s);
mp[s]=0;
while(!q.empty()){
string s=q.front();
q.pop();
rehash(s);
// debugg();
if(check(s)) return mp[s];
for( int i=0;i<4;i++){
for( int j=0;j<=7;j++){
if(now[i][j]!=0||j==0) continue;
int a=now[i][j-1];
a=a+1;
pair<int,int>p=find(a);
if(p.x==-1||p.y==-1||a<10) continue;
swap(now[i][j],now[p.x][p.y]);
string ss=hash();
if(vis.find(ss)==vis.end()){
mp[ss]=mp[s]+1;
vis.insert(ss);
q.push(ss);
}
swap(now[i][j],now[p.x][p.y]);
}
}
}
return -1;
}
int main(){
int t;
cin>>t;
while(t--){
memset(w,0,sizeof(w));
memset(now,0,sizeof(now));
for( int i=0;i<4;i++){
for( int j=1;j<=7;j++){
scanf("%d",&w[i][j]);
}
}
cout<<bfs()<<endl;
}
return 0;
}
不太会,照网上的代码写的,自己的还没有改出来
双向bfs+曼哈顿距离
如果两个人的速度相同,可以用一个队列存储。
本题两个人的速度不同,需要用两个队列存储,对于ghost不需要模拟,只需用哈密顿距离判断即可
(下面代码牛客能过,hdu炸了,没交)
#include
#include
#include
#include
#include
using namespace std;
const int N=900;
string h[N];
int zx[2],zy[2];
struct pos{
int x,y;
}M,G;
int mov[4][2]={0,1,0,-1,1,0,-1,0};
int n,m;
int Time=0;
int vis[N][N][2];
queue<pair<int,int> >q[2];
int check(pair<int,int>p){
int x=p.first,y=p.second;
if(x<0||y<0||x>=n||y>=m) return 0;
if(h[x][y]=='X'||h[x][y]=='Z') return 0;
int dis=min(abs(x-zx[0])+abs(y-zy[0]),abs(x-zx[1])+abs(y-zy[1]));
if(dis<=Time*2) return 0;
return 1;
}
int bfs(int flag){
int sum=q[flag].size();
// cout<
while(sum--){
pair<int,int>now=q[flag].front();
q[flag].pop();
if(check(now)==0) continue;
for( int i=0;i<4;i++){
pair<int,int>temp=now;
temp.first+=mov[i][0];
temp.second+=mov[i][1];
int x=temp.first,y=temp.second;
if(check(temp)==1&&vis[x][y][flag]==0){
if(vis[x][y][!flag]==1) return 1;
vis[x][y][flag]=1;
q[flag].push(temp);
}
}
}
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
cin>>n>>m;
int cnt=0;
Time=0;
memset(vis,0,sizeof(vis));
while(!q[1].empty()) q[1].pop();
while(!q[0].empty()) q[0].pop();
for( int i=0;i<n;i++){
cin>>h[i];
for( int j=0;j<m;j++){
if(h[i][j]=='Z'){
zx[cnt]=i;
zy[cnt]=j;
cnt++;
}
if(h[i][j]=='G'){
G.x=i;
G.y=j;
}
else if(h[i][j]=='M'){
M.x=i;
M.y=j;
}
}
}
//0代表M,可以走三步
// cout<
q[0].push(make_pair(M.x,M.y));
q[1].push(make_pair(G.x,G.y));
vis[M.x][M.y][0]=1,vis[G.x][G.y][1]=1;
while(!q[0].empty()||!q[1].empty()){
Time++;
int res=1;
for( int i=0;i<3;i++)
if(bfs(0)==1){
cout<<Time<<'\n';
goto endd;
}
if(bfs(1)==1){
cout<<Time<<'\n';
goto endd;
}
}
cout<<-1<<'\n';
endd:;
}
return 0;
}