暑假学习记录7.25

92 篇文章 0 订阅

        这两天把bfs的练习和八数码问题干完了,中间有一点小小的卡顿——康托展开。。。由于他给的计算公式和他在代码上的应用有点出入(个人理解,如果没有出入,那只能说明在下是个垃圾。。。)使我看了好久,都看烦了,甚至开始怀疑起了智商,最后才有了一点门道。

long int fact[]={1,1,2,6,24,120,720,5040,40320,362880};
bool cantor(int str[],int n){
long int result=0;
    for(int i=0;i<n;i++){
        int counted=0;
        for(int j=i+1;j<n;j++){
            if(str[i]>str[j])
                counted++;
        }//计算该元素在未出现的元素(也就是位于其后面的元素)中排第几个
        result+=counted*fact[n-i-1]; 
         }//计算这是第几个排列,这个地方fact[]里面的n-i-1以及
        //上面的那一步刚好和书上的公式相反,书上的是a[i]与fact[i-1]对应
        //而代码则是a[i]与fact[n-i-1]对应,这可能是由于计算公式与代码中的i
        //定义不一样导致

        八数码的A*算法(7.26补充)

int cal(int s[],int n){
    int res=0;
    for(int i=0;i<n;i++){
        int x=i/3,y=i%3;
        if(s[i]==0)
            res+=(abs(x-2)+abs(y-2));
        else{
           int w=s[i]-1;
            res+=(abs(x-w/3)+abs(y-w%3));
        }
    }
    return res;
}

poj3126

http://poj.org/problem?id=3126

        去网上搜题解,都说是一个简单搜索,但我觉得好难(吐血)。其实思路感觉不是很难,我也想出来了,但是难在我不会实现啊。。。素数打表我还可以应付,但这个搜的入口有点多,而且搜的条件我也不知道该怎么弄,让一个四位数每一位都改变一下再判断实在是有亿点难。。。看了一个大佬的,脑子还是有点生疏,等有空再回来看看。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<list>
#include<stack>
#include<set>
#define ll long long
#define CHECK(x,y,z) (x>=0&&x<a&&y>=0&&y<b&&z>=0&&z<c&&!(vis[x][y][z])&&val[x][y][z])
//#include<bits/stdc++.h>
using namespace std;
int prime[10005];
int vis[10000],cnt=1;
bool isprime[10005];
    typedef struct{
string s;
int step;
}num;
void dabiao(){//素数打表
    isprime[0]=isprime[1]=1;
    for(int i=2;i<=10000;i++) isprime[i]=1;
    for(int i=2;i<=10000;i++){
        if(isprime[i]) prime[cnt++]=i;
        for(int j=1;j<cnt&&prime[j]*i<=10000;j++){
            isprime[prime[j]*i]=0;
            if(i%prime[j]==0)
                break;
        }
    }
}
int s_int(string s){//将字符串转化为数字
    int ret=0;
    for(int i=0;i<4;i++){
        ret*=10;
        ret+=(s[i]-'0');
    }
    return ret;
}
int bfs(string a,string b){
    queue<num>q;
    num start;
    start.s=a;
    start.step=0;
    q.push(start);
    while(!q.empty()){
        num temp=q.front();
        q.pop();
        if(b.compare(temp.s)==0)
            return temp.step;
        for(int i=0;i<4;i++){
            for(int j=0;j<10;j++){
                if(i==0&&j==0) continue;
                num t=temp;
                t.step++;
                t.s[i]=j+'0';//实现改变四位数的单独一位
                int cmp=s_int(t.s);
                if(!vis[cmp]&&isprime[cmp]==1){
                    vis[cmp]=1;
                    q.push(t);//符合条件标记入队
                }
            }
        }
    }
}
int main(){
    int n;
 // freopen("in.txt","r",stdin);
 dabiao();
cin>>n;
while(n--){
    memset(vis,0,sizeof(vis));
    string a,b;
    cin>>a>>b;
    int ans=bfs(a,b);
    cout<<ans<<endl;
}
return 0;
}

poj3414

        这个题的难点是入口多、情况多(多的我抄都快抄吐了。。。),而且还要打印路径,用回溯也可以做,等学完回溯再回来看看,这是bfs习题的最后一道,做完之后我发现难得不在于思路,而在于如何去实现思路,在这一点上还差很多,需要大量的练习。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<list>
#include<stack>
#include<set>
#define ll long long
#define CHECK(x,y,z) (x>=0&&x<a&&y>=0&&y<b&&z>=0&&z<c&&!(vis[x][y][z])&&val[x][y][z])
//#include<bits/stdc++.h>
using namespace std;
bool vis[110][110];
struct Node{
    int x,y;
    int step;
    int fa;int my;int flag;//my和fa是标记路径的,flag是判断哪一个操作
}node[10010];
queue<Node>q;
void path(int u){//打印路径
    if(node[u].fa==-1)
        return;
    path(node[u].fa);
    if(node[u].flag==11)
        printf("FILL(1)\n");
        else if(node[u].flag==12)
            printf("FILL(2)\n");
        else if(node[u].flag==21)
            printf("DROP(1)\n");
        else if(node[u].flag==22)
            printf("DROP(2)\n");
        else if(node[u].flag==31)
        printf("POUR(1,2)\n");
        else if(node[u].flag==32)
            printf("POUR(2,1)\n");
}

int main(){
 // freopen("in.txt","r",stdin);
    int a,b,c,cnt;
    scanf("%d%d%d",&a,&b,&c);
    memset(vis,false,sizeof(vis));
    vis[0][0]=true;
    cnt=0;
    node[cnt].x=0,node[cnt].y=0,node[cnt].step=0,node[cnt].fa=-1,node[cnt].my=0;
    cnt++;
    q.push(node[0]);
    Node t;
    while(!q.empty()){
        t=q.front();
        if(t.x==c||t.y==c)
            break;
        q.pop();
        if(t.x<a&&!vis[a][t.y]){
            vis[a][t.y]=true;
            node[cnt].x=a,node[cnt].y=t.y,node[cnt].step=t.step+1,node[cnt].my=cnt,node[cnt].fa=t.my,node[cnt].flag=11;
            q.push(node[cnt]);
            cnt++;
        }
        if(t.y<b&&!vis[t.x][b]){
            vis[t.x][b]=true;
            node[cnt].x=t.x,node[cnt].y=b,node[cnt].step=t.step+1,node[cnt].my=cnt,node[cnt].fa=t.my,node[cnt].flag=12;
            q.push(node[cnt]);
            cnt++;
        }
        if(t.x>0&&!vis[0][t.y]){
            vis[0][t.y]=true;
            node[cnt].x=0,node[cnt].y=t.y,node[cnt].step=t.step+1,node[cnt].my=cnt,node[cnt].fa=t.my,node[cnt].flag=21;
            q.push(node[cnt]);
            cnt++;
        }
        if(t.y>0&&!vis[t.x][0]){
            vis[t.x][0]=true;
            node[cnt].x=t.x,node[cnt].y=0,node[cnt].step=t.step+1,node[cnt].my=cnt,node[cnt].fa=t.my,node[cnt].flag=22;
            q.push(node[cnt]);
            cnt++;
        }
        if(t.x>0&&t.y<b){
            if(t.x>=b-t.y&&!vis[t.x-b+t.y][b]){
                vis[t.x-b+t.y][b]=true;
            node[cnt].x=t.x-b+t.y,node[cnt].y=b,node[cnt].step=t.step+1,node[cnt].my=cnt,node[cnt].fa=t.my,node[cnt].flag=31;
            q.push(node[cnt]);
            cnt++;
            }
            else if(t.x<b-t.y&&!vis[0][t.y+t.x]){
                 vis[0][t.y+t.x]=true;
            node[cnt].x=0,node[cnt].y=t.x+t.y,node[cnt].step=t.step+1,node[cnt].my=cnt,node[cnt].fa=t.my,node[cnt].flag=31;
            q.push(node[cnt]);
            cnt++;
            }
        }
        if(t.x<a&&t.y>0){
            if(t.y>=a-t.x&&!vis[a][t.y-a+t.x]){
                 vis[a][t.y-a+t.x]=true;
            node[cnt].x=a,node[cnt].y=t.y-a+t.x,node[cnt].step=t.step+1,node[cnt].my=cnt,node[cnt].fa=t.my,node[cnt].flag=32;
            q.push(node[cnt]);
            cnt++;
            }
            else if(t.y<a-t.x&&!vis[t.x+t.y][0]){
                 vis[t.y+t.x][0]=true;
            node[cnt].x=t.x+t.y,node[cnt].y=0,node[cnt].step=t.step+1,node[cnt].my=cnt,node[cnt].fa=t.my,node[cnt].flag=32;
            q.push(node[cnt]);
            cnt++;
            }
        }
    }
    if(q.empty()) printf("impossible\n");
    else{
        printf("%d\n",t.step);
        path(t.my);
    }
return 0;
}

        8.16回来补上dfs的代码(虽然还是看的题解,无能的我。。。)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y) (x>=0&&x<H&&y>=0&&y<W&&vis[x][y]==0)
//#include<bits/stdc++.h>
using namespace std;
const ll maxx=1e9;
int dir[4][3]={
            {-1,0},
            {1,0},
            {0,-1},
            {0,1},
     };
int vis[110][110],endd,a,b,c;
char option[][10]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(2,1)","POUR(1,2)"},s[2050][15],s2[2050][15];
void dfs(int x,int y,int cnt){
    if(cnt>=endd) return;
    if(x==c||y==c){
        endd=cnt;
        for(int i=0;i<endd;i++)
            strcpy(s2[i],s[i]);
    }
    strcpy(s[cnt],option[0]);
    if(!vis[a][y]){
        vis[a][y]=1;
        dfs(a,y,cnt+1);
        vis[a][y]=0;
    }
    strcpy(s[cnt],option[1]);
    if(!vis[x][b]){
        vis[x][b]=1;
        dfs(x,b,cnt+1);
        vis[x][b]=0;
    }
    strcpy(s[cnt],option[2]);
    if(!vis[0][y]){
        vis[0][y]=1;
        dfs(0,y,cnt+1);
        vis[0][y]=0;
    }
    strcpy(s[cnt],option[3]);
    if(!vis[x][0]){
        vis[x][0]=1;
        dfs(x,0,cnt+1);
        vis[x][0]=0;
    }
    strcpy(s[cnt],option[4]);
    if(x<a&&y>0){
        if(x+y<=a&&!vis[x+y][0]){
            vis[x+y][0]=1;
            dfs(x+y,0,cnt+1);
            vis[x+y][0]=0;
        }
        else if(x+y>a&&!vis[a][y-a+x]){
            vis[a][y-a+x]=1;
            dfs(a,y-a+x,cnt+1);
            vis[a][y-a+x]=0;
        }
    }
    strcpy(s[cnt],option[5]);
    if(y<b&&x>0){
        if(x+y<=b&&!vis[0][x+y]){
            vis[0][x+y]=1;
            dfs(0,x+y,cnt+1);
            vis[0][x+y]=0;
        }
        else if(x+y>b&&!vis[x-b+y][b]){
            vis[x-b+y][b]=1;
            dfs(x-b+y,b,cnt+1);
            vis[x-b+y][b]=0;
        }
    }
 }
int main(){
              //    freopen("in.txt","r",stdin);
    cin>>a>>b>>c;
    endd=1000000;
    dfs(0,0,0);
    if(endd==1000000) cout<<"impossible"<<endl;
    else {
        cout<<endd<<endl;
        for(int i=0;i<endd;i++){
            cout<<s2[i]<<endl;
        }
    }
    return 0;
}

poj1077(八数码问题)

        这个题的难点是打印路径,其他的和书上的八数码没有多大区别,还好上一次碰到过打印路径的题,这次就直接拿过来用了,没想到还真是成了,我测了测程序运行也就0.03s,但c++就是说我超时,最后在g++上AC了。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<list>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y,z) (x>=0&&x<a&&y>=0&&y<b&&z>=0&&z<c&&!(vis[x][y][z])&&val[x][y][z])
//#include<bits/stdc++.h>
using namespace std;
struct Node{
    int state[9];
    int fa;int my;int flag;//my和fa是标记路径的,flag是判断哪一个操作
}node[362885];
int dir[5][5]={{-1,0},{0,-1},{1,0},{0,1}};
int vis[362885]={0};
long int fact[]={1,1,2,6,24,120,720,5040,40320,362880};
bool cantor(int str[],int n){
long int result=0;
    for(int i=0;i<n;i++){
        int counted=0;
        for(int j=i+1;j<n;j++){
            if(str[i]>str[j])
                counted++;
        }
        result+=counted*fact[n-i-1];
    }
    if(!vis[result]){
        vis[result]=1;
        return true;
    }
    else return false;
}
queue<Node>q;
void path(int u){//打印路径
    if(node[u].fa==-1)
        return;
    path(node[u].fa);
    if(node[u].flag==0)
        printf("l");
    else if(node[u].flag==1)
        printf("u");
    else if(node[u].flag==2)
        printf("r");
    else if(node[u].flag==3)
        printf("d");
}

int main(){
 // freopen("in.txt","r",stdin);

char start1[9];
int goal[9],start[9],cnt=0;
for(int i=0;i<8;i++){
    goal[i]=i+1;
}
goal[8]=0;
for(int i=0;i<9;i++){
    scanf("%s",&start1[i]);
    if(start1[i]=='x') start1[i]='0';
}
// clock_t kaishi,jieshu;
    //kaishi=clock();
for(int i=0;i<9;i++) start[i]=start1[i]-'0';
    Node head;
    memcpy(node[0].state,start,sizeof(node[0].state));
    cantor(node[0].state,9); cnt++; q.push(node[0]);
    node[0].fa=-1; node[0].my=0;
    while(!q.empty()){
        head=q.front();
        if(memcmp(head.state,goal,sizeof(goal))==0)
            break;
        q.pop();
        int z=0;
        for(z=0;z<9;z++) if(head.state[z]==0) break;
        int x=z%3; int y=z/3;
        for(int i=0;i<4;i++){
            int newx=x+dir[i][0];
            int newy=y+dir[i][1];
            int nz=newx+3*newy;
            if(newx>=0&&newx<3&&newy>=0&&newy<3){
                memcpy(&node[cnt],&head,sizeof(node[cnt]));
                swap(node[cnt].state[z],node[cnt].state[nz]);
                if(cantor(node[cnt].state,9)){
                        node[cnt].my=cnt,node[cnt].fa=head.my,node[cnt].flag=i;
                    q.push(node[cnt]);
                    cnt++;
                }
            }
        }
    }
if(q.empty()) printf("unsolvable\n");
else{
    path(head.my);
}
   /* jieshu=clock();
    cout<<endl;
    cout<<(double)(jieshu-kaishi)/CLOCKS_PER_SEC<<endl;*/
return 0;
}

        学的A*算法就用A*做了一遍,没想到连以前过不了的c++也过了,还真是个优化算法。一开始想看别人是怎么打的,但实在是看不下去,整体的代码就不一样,看的又烦又想吐,最后知道怎么打A*算法后在自己的代码上改了改,没想到AC了。哎,不要轻易的就认为别人的代码比自己的代码好啊!

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<list>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y,z) (x>=0&&x<a&&y>=0&&y<b&&z>=0&&z<c&&!(vis[x][y][z])&&val[x][y][z])
//#include<bits/stdc++.h>
using namespace std;
struct Node{
    int state[9];int g,h;
    int fa;int my;int flag;//my和fa是标记路径的,flag是判断哪一个操作
    friend bool operator<(Node a,Node b){
    return a.g+a.h>b.g+b.h;
    }
}node[362885];
int dir[5][5]={{-1,0},{0,-1},{1,0},{0,1}};
int vis[362885]={0};
long int fact[]={1,1,2,6,24,120,720,5040,40320,362880};
bool cantor(int str[],int n){
long int result=0;
    for(int i=0;i<n;i++){
        int counted=0;
        for(int j=i+1;j<n;j++){
            if(str[i]>str[j])
                counted++;
        }
        result+=counted*fact[n-i-1];
    }
    if(!vis[result]){
        vis[result]=1;
        return true;
    }
    else return false;
}
int cal(int s[],int n){
    int res=0;
    for(int i=0;i<n;i++){
        int x=i/3,y=i%3;
        if(s[i]==0)
            res+=(abs(x-2)+abs(y-2));
        else{
           int w=s[i]-1;
            res+=(abs(x-w/3)+abs(y-w%3));
        }
    }
    return res;
}
priority_queue<Node>q;
void path(int u){//打印路径
    if(node[u].fa==-1)
        return;
    path(node[u].fa);
    if(node[u].flag==0)
        printf("l");
    else if(node[u].flag==1)
        printf("u");
    else if(node[u].flag==2)
        printf("r");
    else if(node[u].flag==3)
        printf("d");
}

int main(){
 // freopen("in.txt","r",stdin);

char start1[9];
int goal[9],start[9],cnt=0;
for(int i=0;i<8;i++){
    goal[i]=i+1;
}
goal[8]=0;
for(int i=0;i<9;i++){
    scanf("%s",&start1[i]);
    if(start1[i]=='x') start1[i]='0';
}
 //clock_t kaishi,jieshu;
  //  kaishi=clock();
for(int i=0;i<9;i++) start[i]=start1[i]-'0';
    Node head;
    memcpy(node[0].state,start,sizeof(node[0].state));
    cantor(node[0].state,9); cnt++;
    node[0].fa=-1; node[0].my=0;node[0].g=0;q.push(node[0]);
    while(!q.empty()){
        head=q.top();
        if(memcmp(head.state,goal,sizeof(goal))==0)
            break;
        q.pop();
        int z=0;
        for(z=0;z<9;z++) if(head.state[z]==0) break;
        int x=z%3; int y=z/3;
        for(int i=0;i<4;i++){
            int newx=x+dir[i][0];
            int newy=y+dir[i][1];
            int nz=newx+3*newy;
            if(newx>=0&&newx<3&&newy>=0&&newy<3){
                memcpy(&node[cnt],&head,sizeof(node[cnt]));
                swap(node[cnt].state[z],node[cnt].state[nz]);
                node[cnt].g++;
                if(cantor(node[cnt].state,9)){
                        node[cnt].my=cnt,node[cnt].fa=head.my,node[cnt].flag=i;node[cnt].h=cal(node[cnt].state,9);
                    q.push(node[cnt]);
                    cnt++;
                }
            }
        }
    }
if(q.empty()) printf("unsolvable\n");
else{
    path(head.my);
}
/*    jieshu=clock();
    cout<<endl;
    cout<<(double)(jieshu-kaishi)/CLOCKS_PER_SEC<<endl;*/
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

killer_queen4804

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值