POJ2449 Remmarguts' Date

UDF's capital consists of N stations. The hall is numbered S, while the station numbered T denotes prince' current place. M muddy directed sideways connect some of the stations. Remmarguts' path to welcome the princess might include the same station twice or more than twice, even it is the station with number S or T. Different paths with same length will be considered disparate. 1 <= N <= 1000, 0 <= M <= 100000 1 <= K <= 1000

K短路问题,直接dijkstra,第K次得到路经长的时候就是K短路。但是这样时间复杂度\(O(K M \log N)\),不可接受。

考虑用A*算法提高搜索效率,反向预处理处节点\(x\)到终点的最短路长度\(f[x]\),以\(dis+f[x]\)作为比较对象。显然\(f[x] \le g[x]\)。这样虽然时间复杂度上界没变,但是很多点的访问次数小于K,所以该算法能较为快速地求出结果。

#include<iostream>
#include<queue>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long LL;
using namespace std;

co int N=1006;
int n,m,st,ed,k,f[N],cnt[N];
bool v[N];
vector<pair<int,int> > e[N],fe[N];
priority_queue<pair<int,int> > pq;
void dijkstra(){
    memset(f,0x3f,sizeof f);
    f[ed]=0;
    pq.push(make_pair(0,ed));
    while(pq.size()){
        int x=pq.top().second;
        pq.pop();
        if(v[x]) continue;
        v[x]=1;
        for(unsigned i=0;i<fe[x].size();++i){
            int y=fe[x][i].first,z=fe[x][i].second;
            if(f[y]>f[x]+z){
                f[y]=f[x]+z;
                pq.push(make_pair(-f[y],y));
            }
        }
    }
}
void A_star(){
    if(st==ed) ++k;
    pq.push(make_pair(-f[st],st));
    while(pq.size()){
        int x=pq.top().second;
        int dist=-pq.top().first-f[x];
        pq.pop();
        ++cnt[x];
        if(cnt[ed]==k){
            printf("%d\n",dist);
            return;
        }
        for(unsigned i=0;i<e[x].size();++i){
            int y=e[x][i].first,z=e[x][i].second;
            if(cnt[y]!=k) pq.push(make_pair(-f[y]-dist-z,y));
        }
    }
    puts("-1");
}
int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n),read(m);
    for(int i=1,x,y,z;i<=m;++i){
        read(x),read(y),read(z);
        e[x].push_back(make_pair(y,z)),fe[y].push_back(make_pair(x,z));
    }
    read(st),read(ed),read(k);
    dijkstra();
    A_star();
    return 0;
}

POJ1077 Eight

The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:

 1  2  3  4

5 6 7 8
9 10 11 12
13 14 15 x

where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

 1  2  3  4    1  2  3  4    1  2  3  4    1  2  3  4

5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->

The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.



Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and

frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).



In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three

arrangement.

八数码问题,用康托展开记录状态,在A*算法中,用当前状态中所有数字的位置与目标状态中所有数字的位置的曼哈顿距离之和来做估值函数。另外可以用逆序对数奇偶性相同判无解。

#include<iostream>
#include<cmath>
#include<queue>
#include<cstring>
#include<string>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long LL;
using namespace std;

co int N=362886;
int fa[N],f[N];
bool v[N];
co int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
co int jc[10]={1,1,2,6,24,120,720,5040,40320,362880};
struct P{
    int i,x,y;
    string s;
    P(){}
    P(int i,int x,int y,string s):i(i),x(x),y(y),s(s){}
    bool operator<(co P a)co{
        return x+y>a.x+a.y;
    }
};
priority_queue<P> q;
int cantor(string st){
    int len=st.size();
    for(int i=0;i<len;++i)
        if(st[i]=='x'){
            st[i]='0';
            break;
        }
    int ans=1;
    for(int i=0;i<len;++i){
        int num=0;
        for(int j=0;j<i;++j) if(st[j]<st[i]) ++num;
        ans+=(st[i]-'0'-num)*jc[len-i-1];
    }
    return ans;
}
int S(string s){
    int ans=0;
    for(unsigned i=0;i<s.size();++i){
        int r=i/3,c=i%3;
        if(s[i]=='x') ans+=abs(r-2)+abs(c-2);
        else{
            int k=s[i]-'1';
            ans+=abs(r-k/3)+abs(c-k%3);
        }
    }
    return ans;
}
bool bfs(string st){
    string ed="12345678x";
    memset(fa,-1,sizeof fa);
    memset(f,-1,sizeof f);
    int k;
    for(int i=0;i<10;++i)
        if(st[i]=='x'){
            k=i;
            break;
        }
    P p=P(k,0,S(st),st);
    q.push(p);
    v[cantor(st)]=1;
    while(q.size()){
        p=q.top();
        if(p.s==ed) return 1;
        q.pop();
        int r=p.i/3,c=p.i%3;
        for(int i=0;i<4;++i){
            int nx=r+dx[i],ny=c+dy[i];
            if(nx<0||nx>2||ny<0||ny>2) continue;
            string s=p.s;
            swap(s[p.i],s[nx*3+ny]);
            int k=cantor(s);
            if(v[k]) continue;
            v[k]=1,fa[k]=cantor(p.s),f[k]=i;
            P np=P(nx*3+ny,p.x+1,S(s),s);
            q.push(np);
        }
    }
    return 0;
}
int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    string st="";
    for(int i=1;i<=9;++i){
        char s[2];
        scanf("%s",s);
        st+=s[0];
    }
    int cnt=0;
    for(unsigned i=0;i<st.size();++i) if(st[i]!='x')
        for(unsigned j=0;j<i;++j)
            if(st[j]!='x'&&st[j]>st[i]) ++cnt;
    if(cnt&1){
        puts("unsolvable");
        return 0;
    }
    vector<int> ans;
    if(bfs(st)){
        int k=cantor("12345678x");
        while(k!=-1){
            ans.push_back(f[k]);
            k=fa[k];
        }
        for(unsigned i=ans.size()-1;i<ans.size();--i) // correct due to unsigned
            if(ans[i]==0) putchar('u');
            else if(ans[i]==1) putchar('l');
            else if(ans[i]==2) putchar('d');
            else if(ans[i]==3) putchar('r');
    }else puts("unsolvable");
    return 0;
}

POJ3460 Booksort

The Leiden University Library has millions of books. When a student wants to borrow a certain book, he usually submits an online loan form. If the book is available, then the next day the student can go and get it at the loan counter. This is the modern way of borrowing books at the library.

There is one department in the library, full of bookcases, where still the old way of borrowing is in use. Students can simply walk around there, pick out the books they like and, after registration, take them home for at most three weeks.

Quite often, however, it happens that a student takes a book from the shelf, takes a closer look at it, decides that he does not want to read it, and puts it back. Unfortunately, not all students are very careful with this last step. Although each book has a unique identification code, by which the books are sorted in the bookcase, some students put back the books they have considered at the wrong place. They do put it back onto the right shelf. However, not at the right position on the shelf.

Other students use the unique identification code (which they can find in an online catalogue) to find the books they want to borrow. For them, it is important that the books are really sorted on this code. Also for the librarian, it is important that the books are sorted. It makes it much easier to check if perhaps some books are stolen: not borrowed, but yet missing.

Therefore, every week, the librarian makes a round through the department and sorts the books on every shelf. Sorting one shelf is doable, but still quite some work. The librarian has considered several algorithms for it, and decided that the easiest way for him to sort the books on a shelf, is by sorting by transpositions: as long as the books are not sorted,

  1. take out a block of books (a number of books standing next to each other),
  2. shift another block of books from the left or the right of the resulting ‘hole’, into this hole,
  3. and put back the first block of books into the hole left open by the second block.

One such sequence of steps is called a transposition.

The following picture may clarify the steps of the algorithm, where X denotes the first block of books, and Y denotes the second block.

Original situation:
After step 1:
After step 2:
After step 3:

Of course, the librarian wants to minimize the work he has to do. That is, for every bookshelf, he wants to minimize the number of transpositions he must carry out to sort the books. In particular, he wants to know if the books on the shelf can be sorted by at most 4 transpositions. Can you tell him?

考虑搜索,每一层有\(\sum_{i=1}^n (n-i+1)(n-i)=560\)种分支,不能全部搜完,所以要剪枝。由于一次操作最多让3个数的后继变对,所以操作次数至少是后继不对的数的个数除以3上取整,利用这个性质来剪枝。显然要用迭代搜索,所以这是一个IDA*算法。

#include<iostream>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long LL;

co int N=20;
int n,a[N],dep;
int gj(){
    int cnt=0;
    for(int i=1;i<n;++i)
        if(a[i]+1!=a[i+1]) ++cnt;
    if(a[n]!=n) return cnt;
    return cnt;
}
void work(int l,int r,int t){
    int b[N],p=r;
    for(int i=l;i<=t;++i){
        b[i]=a[++p];
        if(p==t) p=l-1;
    }
    for(int i=l;i<=t;++i) a[i]=b[i];
}
bool dfs(int now){
    int cnt=gj();
    if(!cnt) return 1;
    if(3*now+cnt>3*dep) return 0;
    int c[N];
    memcpy(c,a,sizeof c);
    for(int l=1;l<=n;++l)
        for(int r=l;r<=n;++r)
            for(int t=r+1;t<=n;++t){
                work(l,r,t);
                if(dfs(now+1)) return 1;
                memcpy(a,c,sizeof a);
            }
    return 0;
}
void Booksort(){
    read(n);
    for(int i=1;i<=n;++i) read(a[i]);
    for(dep=0;dep<=4;++dep)
        if(dfs(0)){
            printf("%d\n",dep);
            return;
        }
    puts("5 or more");
}
int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int t=read<int>();
    while(t--) Booksort();
    return 0;
}

POJ2286 The Rotation Game

The rotation game uses a # shaped board, which can hold 24 pieces of square blocks (see Fig.1). The blocks are marked with symbols 1, 2 and 3, with exactly 8 pieces of each kind.



Initially, the blocks are placed on the board randomly. Your task is to move the blocks so that the eight blocks placed in the center square have the same symbol marked. There is only one type of valid move, which is to rotate one of the four lines, each consisting of seven blocks. That is, six blocks in the line are moved towards the head by one block and the head block is moved to the end of the line. The eight possible moves are marked with capital letters A to H. Figure 1 illustrates two consecutive moves, move A and move C from some initial configuration.

要字典序最小,考虑迭代加深搜索,剪枝优化:

  1. 每次不做上一次操作的逆操作
  2. 当前中央8格中最多的数字为k,其他的数字有m个,至少要做m次操作才能将这m个数字都换成k。
 #include<iostream>
#include<cstring>
#include<vector>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long LL;
using namespace std;

int a[9][9],dep;
vector<char> ans;
void work(int k){
    if(k==1){
        for(int i=1;i<8;++i) a[i-1][3]=a[i][3];
        a[7][3]=a[0][3];
    }else if(k==2){
        for(int i=1;i<8;++i) a[i-1][5]=a[i][5];
        a[7][5]=a[0][5];
    }else if(k==3){
        for(int i=7;i;--i) a[3][i+1]=a[3][i];
        a[3][1]=a[3][8];
    }else if(k==4){
        for(int i=7;i;--i) a[5][i+1]=a[5][i];
        a[5][1]=a[5][8];
    }else if(k==5){
        for(int i=7;i;--i) a[i+1][5]=a[i][5];
        a[1][5]=a[8][5];
    }else if(k==6){
        for(int i=7;i;--i) a[i+1][3]=a[i][3];
        a[1][3]=a[8][3];
    }else if(k==7){
        for(int i=1;i<8;++i) a[5][i-1]=a[5][i];
        a[5][7]=a[5][0];
    }else{
        for(int i=1;i<8;++i) a[3][i-1]=a[3][i];
        a[3][7]=a[3][0];
    }
}
int gj(){
    int num[4];
    num[1]=num[2]=num[3]=0;
    for(int i=3;i<6;++i)
        for(int j=3;j<6;++j){
            if(i==4&&j==4) continue;
            ++num[a[i][j]];
        }
    return 8-max(num[1],max(num[2],num[3]));
}
bool dfs(int now){
    int cnt=gj();
    if(!cnt) return 1;
    if(now+cnt>dep) return 0;
    int b[9][9];
    memcpy(b,a,sizeof b);
    for(int i=1;i<9;++i){
        if(ans.size()){
            int k=ans.back();
            if(k-'A'+1==1&&i==6) continue;
            if(k-'A'+1==2&&i==5) continue;
            if(k-'A'+1==3&&i==8) continue;
            if(k-'A'+1==4&&i==7) continue;
            if(k-'A'+1==5&&i==2) continue;
            if(k-'A'+1==6&&i==1) continue;
            if(k-'A'+1==7&&i==4) continue;
            if(k-'A'+1==8&&i==3) continue;
        }
        ans.push_back(i+'A'-1);
        work(i);
        if(dfs(now+1)) return 1;
        ans.pop_back();
        memcpy(a,b,sizeof a);
    }
    return 0;
}
void The_Rotation_Game(){
    read(a[1][5]),read(a[2][3]),read(a[2][5]);
    for(int i=1;i<8;++i) read(a[3][i]);
    read(a[4][3]),read(a[4][5]);
    for(int i=1;i<8;++i) read(a[5][i]);
    read(a[6][3]),read(a[6][5]),read(a[7][3]),read(a[7][5]);
    ans.clear();
    dep=0;
    while(!dfs(0)) ++dep;
    if(!dep) puts("No moves needed");
    else{
        for(unsigned i=0;i<ans.size();++i)
            putchar(ans[i]);
        puts("");
    }
    printf("%d\n",a[3][3]);
}
int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    while(read(a[1][3])) The_Rotation_Game();
    return 0;
}

A*专题训练的更多相关文章

  1. DP专题训练之HDU 2955 Robberies

    打算专题训练下DP,做一道帖一道吧~~现在的代码风格完全变了~~大概是懒了.所以.将就着看吧~哈哈 Description The aspiring Roy the Robber has seen a ...

  2. dp专题训练

    ****************************************************************************************** 动态规划 专题训练 ...

  3. bryce1010专题训练——LCT&&树链剖分

    LCT&&树链剖分专题 参考: https://blog.csdn.net/forever_wjs/article/details/52116682

  4. DP专题训练之HDU 1087 Super Jumping!

    Description Nowadays, a kind of chess game called "Super Jumping! Jumping! Jumping!" is ve ...

  5. DP专题训练之HDU 1506 Largest Rectangle in a Histogram

    Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...

  6. DP专题训练之HDU 1231 最大连续子序列

    Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j < ...

  7. DP专题训练之HDU 1864 最大报销额

    做DP一定要注意数组的大小,嗯,就是这样~ Description 现有一笔经费可以报销一定额度的发票.允许报销的发票类型包括买图书(A类).文具(B类).差旅(C类),要求每张发票的总额不得超过10 ...

  8. bzoj专题训练

    //http://blog.csdn.net/PoPoQQQ/article/category/2542243

  9. 算法专题训练 搜索a-T3 Ni骑士(ni)

    搞了半天八数码弄不出来就只好来打题解  这道题是在搜索a碰到的(链接: http://pan.baidu.com/s/1jG9rQsQ ) 感觉题目最大亮点就是这英文简写"ni", ...

  10. 图论专题训练1-D(K步最短路,矩阵连乘)

    题目链接 /* *题目大意: *求出从i到j,刚好经过k条边的最短路; * *矩阵乘法的应用之一(国家队论文): *矩阵乘法不满足交换律,矩阵乘法满足结合律; *给定一个有向图,问从A点恰好走k步(允 ...

随机推荐

  1. 系统管理命令之tty

    在Linux操作系统中,所有外围设备都有其名称与代号,这些名称代号以特殊文件的类型存放于/dev目录下.你可以执行tty指令查询目前使用的终端机的文件名称. 1.命令帮助: # tty -- help ...

  2. 【android】开发中遇到的一些问题

    1:华为输入法,输入框为ACTION_DONE模式,ActionId是 UNSPECIFIED EditText对象.setImeOptions(EditorInfo.IME_ACTION_DONE) ...

  3. ubuntu14.04 安装apache+mysql+php

    1.安装apache sudo apt-get update sudo apt-get install apache2 这时http://你机器的ip,就可以访问了. 2.安装mysql sudo a ...

  4. BNUOJ 26474 Bread Sorting

    /*给出n个原始顺序的数,再给出要排成目标状态顺序,每次从第一个数列中选择三个,把这三个数中最右边的数放在最左边,然后其他两个数右 移一个单位,为你从原始状态能不能排序成目标状态. 本人YY的结论,从 ...

  5. 【软件位置】Linux查看软件安装的位置

    如果我们在Linux 系统上安装了某个软件,我们可以通过如下的三种方式来确定. 一.        Which 命令 Shell 的which 命令可以找出相关命令是否已经在搜索路径中. 如: [ro ...

  6. [SpringBoot] - 配置文件的多种形式及JSR303数据校验

    Springboot配置文件: application.yml   application.properties(自带) yml的格式写起来稍微舒服一点 在application.properties ...

  7. pix2pix-tensorflow搭建及其使用

    目录 pix2pix-tensorflow搭建过程 1. 环境搭建 2. 环境说明 3. 开始搭建 4. 训练结果说明 5. 数据集 5.1 图片格式说明 5.3 从先用图片创建图像对 5.4 如何进 ...

  8. eclipse下maven springMVC 整合 mybatis

    参考文档:http://blog.csdn.net/zhshulin/article/details/37956105   1.搭建maven工程,具体参见我另一篇博客:http://www.cnbl ...

  9. 雷林鹏分享:Ruby 发送邮件 - SMATP

    Ruby 发送邮件 - SMATP SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式. ...

  10. .net core部署到linux

    1.Install the .NET SDK 我的服务器是腾讯云的Ubuntu 16 注册Microsoft密钥和订阅源 wget -q https://packages.microsoft.com/ ...