2012年8月13日 星期一

uva 153 - Permalex



 Permalex 

Given a string of characters, we can permute the individual characters to make new strings. If we can impose an ordering on the characters (say alphabetic sequence), then the strings themselves can be ordered and any given permutation can be given a unique number designating its position in that ordering. For example the string `acab' gives rise to the following 12 distinct permutations:

tabular21

Thus the string `acab' can be characterised in this sequence as 5.

Write a program that will read in a string and determine its position in the ordered sequence of permutations of its constituent characters. Note that numbers of permutations can get very large; however we guarantee that no string will be given whose position is more than tex2html_wrap_inline31 .

Input and Output

Input will consist of a series of lines, each line containing one string. Each string will consist of up to 30 lower case letters, not necessarily distinct. The file will be terminated by a line consisting of a single #.

Output will consist of a series of lines, one for each line of the input. Each line will consist of the position of the string in its sequence, right justified in a field of width 10.

Sample input


bacaa
abc
cba
#

Sample output


        15
         1
         6

permutation 

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<queue>
#include<math.h>
#include<algorithm>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define DBG 0

using namespace std;

string S;
vector<int>prime;
int base[50],cur[50];
int notp[30];

void getP(){
notp[0]=notp[1]=1;
int b;
rep(i,30)
if(!notp[i]){
prime.push_back(i);
if(DBG)printf("%d\n",i);
for(int b=i*2;b<30;b+=i)notp[b]=1;
}
}
void getEle(int c){
int a;
REP(i,2,c+1){
a=i;
rep(j,prime.size()){
while(a%prime[j]==0)a/=prime[j],base[prime[j]]++;
if(a==1)break;
}
}
}
void getCur(int c){
int a;
REP(i,2,c+1){
a=i;
rep(j,prime.size()){
while(a%prime[j]==0){
a/=prime[j];
if(base[prime[j]])base[prime[j]]--;
else cur[prime[j]]++;
}
if(a==1)break;
}
}
}
int getN(string s,int a,int b){
int cnt[26];
memset(cnt,0,sizeof(cnt));
memset(cur,0,sizeof(cur));
REP(i,a,b)cnt[s[i]-'a']++;
rep(i,26)if(cnt[i]>1)getEle(cnt[i]);
getCur(b-a);
int c=1;
REP(i,2,32)if(cur[i])c*=int(pow(i,cur[i])+0.5);
if(DBG)printf("getN: %s\n",s.c_str());
return c;
}
void getNum(){
int c=0;
char d;
bool add[256];
string s;
rep(i,S.size()-1){
memset(add,0,sizeof(add));
REP(j,i+1,S.size())
if(S[j]<S[i]&&!add[S[j]]){
s=S;
add[s[j]]=1;
d=s[i],s[i]=s[j],s[j]=d;
c+=getN(s,i+1,s.size());
}
}
printf("%10d\n",c+1);
}
int main(){
getP();
while(cin>>S){
if(S[0]=='#')break;
getNum();
}
}

uva 750 - 8 Queens Chess Problem



  8 Queens Chess Problem 

In chess it is possible to place eight queens on the board so that no one queen can be taken by any other. Write a program that will determine all such possible arrangements for eight queens given the initial position of one of the queens.
Do not attempt to write a program which evaluates every possible 8 configuration of 8 queens placed on the board. This would require 88 evaluations and would bring the system to its knees. There will be a reasonable run time constraint placed on your program.

Input 

The first line of the input contains the number of datasets, and it's followed by a blank line. Each dataset will be two numbers separated by a blank. The numbers represent the square on which one of the eight queens must be positioned. A valid square will be represented; it will not be necessary to validate the input.To standardize our notation, assume that the upper left-most corner of the board is position (1,1). Rows run horizontally and the top row is row 1. Columns are vertical and column 1 is the left-most column. Any reference to a square is by row then column; thus square (4,6) means row 4, column 6.
Each dataset is separated by a blank line.


Output 

Output for each dataset will consist of a one-line-per-solution representation.Each solution will be sequentially numbered $1 \dots N$. Each solution will consist of 8 numbers. Each of the 8 numbers will be the ROW coordinate for that solution. The column coordinate will be indicated by the order in which the 8 numbers are printed. That is, the first number represents the ROW in which the queen is positioned in column 1; the second number represents the ROW in which the queen is positioned in column 2, and so on.
The sample input below produces 4 solutions. The full 8$\times$8 representation of each solution is shown below.

DO NOT SUBMIT THE BOARD MATRICES AS PART OF YOUR SOLUTION!

   SOLUTION 1           SOLUTION 2           SOLUTION 3           SOLUTION 4

1 0 0 0 0 0 0 0      1 0 0 0 0 0 0 0      1 0 0 0 0 0 0 0      1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0      0 0 0 0 0 0 1 0      0 0 0 0 0 1 0 0      0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0      0 0 0 1 0 0 0 0      0 0 0 0 0 0 0 1      0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1      0 0 0 0 0 1 0 0      0 0 1 0 0 0 0 0      0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0      0 0 0 0 0 0 0 1      0 0 0 0 0 0 1 0      0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0      0 1 0 0 0 0 0 0      0 0 0 1 0 0 0 0      0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0      0 0 0 0 1 0 0 0      0 1 0 0 0 0 0 0      0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0      0 0 1 0 0 0 0 0      0 0 0 0 1 0 0 0      0 0 0 1 0 0 0 0
Submit only the one-line, 8 digit representation of each solution as described earlier. Solution #1 below indicates that there is a queen at Row 1, Column 1; Row 5, Column 2; Row 8, Column 3; Row 6, Column 4; Row 3,Column 5; ... Row 4, Column 8.
Include the two lines of column headings as shown below in the sample output and print the solutions in lexicographical order.
Print a blank line between datasets.

Sample Input 


1

1 1

Sample Output 


SOLN       COLUMN
 #      1 2 3 4 5 6 7 8

 1      1 5 8 6 3 7 2 4
 2      1 6 8 3 7 4 2 5
 3      1 7 4 6 8 2 5 3
 4      1 7 5 8 2 4 6 3



Miguel A. Revilla
2000-02-09

DFS

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<queue>
#include<math.h>
#include<algorithm>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define DBG 0

using namespace std;

int R,C;
bool thr[8][8];
int pad[4][2];
vector<vector<int> >res;
vector<int>cur;
void init(){
    pad[0][0]=-1,pad[0][1]=-1,
    pad[1][0]=-1,pad[1][1]=1,
    pad[2][0]=1,pad[2][1]=1,
    pad[3][0]=1,pad[3][1]=-1;
}
bool valid(int a,int b){
    return a>=0&&b>=0&&a<8&&b<8;
}
void add(int a,int b){
    rep(i,8)thr[a][i]=1,thr[i][b]=1;
    int c,d;
    rep(i,4){
        c=a,d=b;
        while(valid(c+pad[i][0],d+pad[i][1]))c+=pad[i][0],d+=pad[i][1],thr[c][d]=1;
    }
}
void DFS(int c){
    if(c==8){res.push_back(cur);return;}
    if(c==C){cur.push_back(R),DFS(c+1),cur.erase(cur.end()-1);}
    else{
        bool tthr[8][8];
        rep(i,8){
            if(!thr[i][c]){
                memcpy(tthr,thr,sizeof(thr));
                cur.push_back(i);
                if(DBG)printf("push %d %d\n",i,c);
                add(i,c);
                DFS(c+1);
                memcpy(thr,tthr,sizeof(thr));
                cur.erase(cur.end()-1);
            }
        }
    }
}
void getNum(){
    res.clear();
    if(DBG)rep(i,8){rep(j,8)printf("%d ",thr[i][j]);printf("\n");}
    DFS(0);
    rep(i,res.size()){
        printf("%2d      ",i+1);
        rep(j,res[i].size()){if(j)printf(" ");printf("%d",res[i][j]+1);}
        printf("\n");
    }
}
int main(){
    int a;
    bool ll=0;
    cin>>a;
    init();
    
    rep(i,a){
        memset(thr,0,sizeof(thr));
        cin>>R>>C,R--,C--;
        add(R,C);
        if(ll)printf("\n");ll=1;
        printf("SOLN       COLUMN\n #      1 2 3 4 5 6 7 8\n\n");
        getNum();
    }
}

uva 439 - Knight Moves



 Knight Moves 

A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight moves between two given squares and that, once you have accomplished this, finding the tour would be easy.
Of course you know that it is vice versa. So you offer him to write a program that solves the "difficult" part.

Your job is to write a program that takes two squares a and b as input and then determines the number of knight moves on a shortest route from a to b.

Input Specification

The input file will contain one or more test cases. Each test case consists of one line containing two squares separated by one space. A square is a string consisting of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard.

Output Specification

For each test case, print one line saying "To get from xx to yy takes n knight moves.".

Sample Input


e2 e4
a1 b2
b2 c3
a1 h8
a1 h7
h8 a1
b1 c3
f6 f6

Sample Output


To get from e2 to e4 takes 2 knight moves.
To get from a1 to b2 takes 4 knight moves.
To get from b2 to c3 takes 2 knight moves.
To get from a1 to h8 takes 6 knight moves.
To get from a1 to h7 takes 5 knight moves.
To get from h8 to a1 takes 6 knight moves.
To get from b1 to c3 takes 1 knight moves.
To get from f6 to f6 takes 0 knight moves.
BFS
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<queue>
#include<math.h>
#include<algorithm>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define DBG 0

using namespace std;

int R1,C1,R2,C2;
string S1,S2;
bool visit[8][8];
int pad[8][2];
struct Node{
Node(int a,int b,int c):r(a),c(b),dis(c){}
int r,c,dis;
};
void init(){
pad[0][0]=-1,pad[0][1]=-2,
pad[1][0]=-1,pad[1][1]=2,
pad[2][0]=1,pad[2][1]=2,
pad[3][0]=1,pad[3][1]=-2,
pad[4][0]=-2,pad[4][1]=-1,
pad[5][0]=-2,pad[5][1]=1,
pad[6][0]=2,pad[6][1]=1,
pad[7][0]=2,pad[7][1]=-1;
}
bool valid(int a,int b){
return a>=0&&b>=0&&a<8&&b<8;
}
void getNum(){
int ans=0;
bool f=0;
memset(visit,0,sizeof(visit));
queue<Node>q;
q.push(Node(R1,C1,0));
if(!(R1==R2&&C1==C2))
while(q.size()){
int x=q.front().r,y=q.front().c,dis=q.front().dis;
q.pop();
visit[x][y]=1;
if(DBG)printf("x y dis %d %d %d\n",x,y,dis);
rep(i,8){
int c=x+pad[i][0],d=y+pad[i][1];
if(valid(c,d)&&!visit[c][d]){
if(c==R2&&d==C2){ans=dis+1,f=1;break;}
q.push(Node(c,d,dis+1));
}
}
if(f)break;
}
printf("To get from %s to %s takes %d knight moves.\n",S1.c_str(),S2.c_str(),ans);
}
int main(){
init();
while(cin>>S1>>S2){
R1=(S1[1]-'1'),C1=S1[0]-'a';
R2=(S2[1]-'1'),C2=S2[0]-'a';
if(DBG)printf("%d %d %d %d\n",R1,C1,R2,C2);
getNum();
}
}

2012年8月10日 星期五

uva 278 - Chess



 Chess 

Almost everyone knows the problem of putting eight queens on an tex2html_wrap_inline30 chessboard such that no Queen can take another Queen. Jan Timman (a famous Dutch chessplayer) wants to know the maximum number of chesspieces of one kind which can be put on an tex2html_wrap_inline32 board with a certain size such that no piece can take another. Because it's rather difficult to find a solution by hand, he asks your help to solve the problem.

He doesn't need to know the answer for every piece. Pawns seems rather uninteresting and he doesn't like Bishops anyway. He only wants to know how many Rooks, Knights, Queens or Kings can be placed on one board, such that one piece can't take any other.

Input

The first line of input contains the number of problems. A problem is stated on one line and consists of one character from the following set rkQK, meaning respectively the chesspieces Rook, Knight, Queen or King. The character is followed by the integers m ( tex2html_wrap_inline36 ) and n ( tex2html_wrap_inline40 ), meaning the number of rows and the number of columns or the board.

Output

For each problem specification in the input your program should output the maximum number of chesspieces which can be put on a board with the given formats so they are not in position to take any other piece.


Note: The bottom left square is 1, 1.

Sample Input


2
r 6 7
k 8 8

Sample Output


6
32

chess, no need to use DFS >"<


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<map>
#include<math.h>
#include<algorithm>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define DBG 0

using namespace std;

int R,C,T,G;
bool tht[10][10];
int mp[128];
void init(){
mp['r']=0,mp['k']=1,mp['Q']=2,mp['K']=3;
}
void getNum(){
int ans;
if(T==3){R=R%2?R+1:R,C=C%2?C+1:C,printf("%d\n",R*C/4);return;}
if(T==1){ans=R*C/2,printf("%d\n",ans);return;}
if(T==0||T==2){printf("%d\n",G);return;}
}
int main(){
int a,b,c;
string s;
cin>>a;
init();
rep(i,a){
cin>>s>>R>>C;
G=min(R,C);
if(DBG)printf("R C %d %d\n",R,C);
T=mp[s[0]];
getNum();
}
}

uva 167 - The Sultan's Successors



 The Sultan's Successors 

The Sultan of Nubia has no children, so she has decided that the country will be split into up to k separate parts on her death and each part will be inherited by whoever performs best at some test. It is possible for any individual to inherit more than one or indeed all of the portions. To ensure that only highly intelligent people eventually become her successors, the Sultan has devised an ingenious test. In a large hall filled with the splash of fountains and the delicate scent of incense have been placed k chessboards. Each chessboard has numbers in the range 1 to 99 written on each square and is supplied with 8 jewelled chess queens. The task facing each potential successor is to place the 8 queens on the chess board in such a way that no queen threatens another one, and so that the numbers on the squares thus selected sum to a number at least as high as one already chosen by the Sultan. (For those unfamiliar with the rules of chess, this implies that each row and column of the board contains exactly one queen, and each diagonal contains no more than one.)

Write a program that will read in the number and details of the chessboards and determine the highest scores possible for each board under these conditions. (You know that the Sultan is both a good chess player and a good mathematician and you suspect that her score is the best attainable.)

Input

Input will consist of k (the number of boards), on a line by itself, followed by k sets of 64 numbers, each set consisting of eight lines of eight numbers. Each number will be a positive integer less than 100. There will never be more than 20 boards.

Output

Output will consist of k numbers consisting of your k scores, each score on a line by itself and right justified in a field 5 characters wide.

Sample input


1
 1  2  3  4  5  6  7  8
 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
48 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64

Sample output


  260

eight queen 

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<map>
#include<math.h>
#include<algorithm>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define DBG 0

using namespace std;

int brd[8][8];
bool row[8],tht[8][8];
vector<pair<int,int> >pos;
bool threat(int r,int c){
rep(i,pos.size()){
int x=pos[i].first,y=pos[i].second;
if(x==r||abs(x-r)==abs(y-c))return 1;
}
return 0;
}

int DFS(int c,int d){
if(c==8)return d;
int m=0;
rep(i,8)
if(!threat(i,c)){
pos.push_back(make_pair(i,c)),m=max(m,DFS(c+1,d+brd[i][c]));
pos.erase(pos.end()-1);
}
return m;
}
void getNum(){
printf("%5d\n",DFS(0,0));
}
int main(){
int a;
cin>>a;
rep(i,a){
rep(i,8)rep(j,8)scanf("%d",&brd[i][j]);
getNum();
}
}

2012年8月9日 星期四

uva 793 - Network Connections



  Network Connections 

Bob, who is a network administrator, supervises a network of computers. He is keeping a log connections between the computers in the network. Each connection is bi-directional. Two computers are interconnected if they are directly connected or if they are interconnected with the same computer. Occasionally, Bob has to decide, quickly, whether two given computers are connected, directly or indirectly, according to the log information.


Write a program which based on information input from a text file counts the number of successful and the number of unsuccessful answers to the questions of the kind :


is computeri interconnected with computerj ?

Input and Output 

The first line of the input contains the number of dataset, and it's followed by a blank line. Each dataset is defined as follows:
1.
The number of computers in the network (a strictly positive integer);
2.
A list of pairs of the form:
(a)
c computeri computerj, where computeri and computerj are integers from 1 to$no\_of\_computers$. A pair of this form shows that computeri and computerj get interconnected.
(b)
q computeri computerj, where computeri and computerj are integers from 1 to$no\_of\_computers$. A pair of this form stands for the question: is computeri interconnectedwith computerj?
There's a blank line between datasets.
Each pair is on a separate line. Pairs can appear in any order, regardless of their type. The log is updated after each pair of type (a) and each pair of type (b) is processed according to the current network configuration.


For example, the input file illustrated in the sample below corresponds to a network of 10 computers and 7 pairs. There are N1 successfully answered questions and N2 unsuccessfully answered questions. The program prints these two numbers to the standard output on the same line, in the order: successful answers, unsuccessful answers, as shown in the sample output. Print a blank line between datasets.

Sample Input 

1

10
c 1 5
c 2 7
q 7 1
c 3 9
q 9 6
c 2 5
q 7 5

Sample Input 

1,2



Miguel Revilla
2001-01-05

union-set 

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define DBG 0

using namespace std;

int N;
int *par;
int find(int a){
if(par[a]==a)return a;
int c=a;
while(par[a]!=a)a=par[a];
return par[c]=a;
}
void merge(int to,int from){
int a=find(to),b=find(from);
par[b]=a;
}
int main(){
int a,b,c,c1,c2;
char nds[100];
bool ll=0;
scanf("%d",&a);
rep(i,a){
c1=c2=0;
scanf("%d ",&N);
par=(int *)malloc(N*sizeof(int));
rep(i,N)par[i]=i;
if(DBG)printf("N %d\n",N);
while(fgets(nds,100,stdin)){
if(nds[0]=='\n')break;
if(nds[0]=='c'){
sscanf(&nds[1],"%d%d",&b,&c),c--,b--;
if(find(b)!=find(c))merge(b,c);
}
else if(nds[0]=='q'){
sscanf(&nds[1],"%d%d",&b,&c),c--,b--;
if(find(b)!=find(c))c2++;
else c1++;
}
}
if(ll)printf("\n");ll=1;
printf("%d,%d\n",c1,c2);
}
}

uva 10397 - Connect the Campus


Problem E
Connect the Campus
Input: standard input
Output: standard output
Time Limit: 2 seconds
Many new buildings are under construction on the campus of the University of Waterloo. The university has hired bricklayers, electricians, plumbers, and a computer programmer. A computer programmer? Yes, you have been hired to ensure that each building is connected to every other building (directly or indirectly) through the campus network of communication cables.
We will treat each building as a point specified by an x-coordinate and a y-coordinate. Each communication cable connects exactly two buildings, following a straight line between the buildings. Information travels along a cable in both directions. Cables can freely cross each other, but they are only connected together at their endpoints (at buildings).
You have been given a campus map which shows the locations of all buildings and existing communication cables. You must not alter the existing cables. Determine where to install new communication cables so that all buildings are connected. Of course, the university wants you to minimize the amount of new cable that you use.
Fig: University of Waterloo Campus

Input
The input file describes several test case.  The description of each test case is given below:
The first line of each test case contains the number of buildings N (1<=N<=750). The buildings are labeled from 1 to N. The next N lines give the x and y coordinates of the buildings. These coordinates are integers with absolute values at most 10000. No two buildings occupy the same point. After that there is a line containing the number of existing cables M (0 <= M <= 1000) followed by M lines describing the existing cables. Each cable is represented by two integers: the building numbers which are directly connected by the cable. There is at most one cable directly connecting each pair of buildings.
Output
For each set of input, output in a single line the total length of the new cables that you plan to use, rounded to two decimal places.
Sample Input
4
103 104
104 100
104 103
100 100
1
4 2
4
103 104
104 100
104 103
100 100
1
4 2

Sample Output
4.41
4.41

(Problem-setters: G. Kemkes & G. V. Cormack, CS Dept, University of Waterloo)

“A man running away from a tiger need not run faster than the tiger but run faster than the friend.”

MST - kruskal (note: use double instead of float to avoid floating-point error)

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<set>
#include<math.h>
#include<algorithm>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define DBG 0

using namespace std;

int N,E;
bool con[750][750];
vector<pair<int,int> >ver;
int par[750];
struct Edge{
    Edge(int a,int b,double dis):a(a),b(b),dis(dis){}
    int a,b;
    double dis;
    bool operator <(const Edge a)const{return dis<a.dis;}
};
vector<Edge>eg;

int find(int a){
    if(par[a]==a)return a;
    int c=a;
    while(par[a]!=a)a=par[a];
    return par[c]=a;
}
void merge(int to,int from){
    int a=find(to),b=find(from);
    par[b]=a;
}
void getNum(){  
    double sum=0;
    if(E<N-1){
        int c=E; 
        sort(eg.begin(),eg.end());
        rep(i,eg.size()){
            int a=eg[i].a,b=eg[i].b;
            if(find(a)!=find(b)){
                if(DBG)printf("eg %d %d\n",a+1,b+1);
                merge(a,b),sum+=eg[i].dis;
                if(c==N-1)break;
            } 
        }
    }
    printf("%.2f\n",sum);
}
double dist(double a,double b,double c,double d){
    return sqrt(pow(a-c,2)+pow(b-d,2));
}
void getDis(){
    rep(i,N)REP(j,i+1,N){
        if(!con[i][j])
            eg.push_back(Edge(i,j,dist(ver[i].first,ver[i].second,ver[j].first,ver[j].second)));
    }
}
int main(){
    int a,b,c,d,x,y;
    while(cin>>N){
        eg.clear(),E=0;
        ver.clear(),memset(con,0,sizeof(con));
        rep(i,N)par[i]=i;           //init
        rep(i,N)cin>>x>>y,ver.push_back(make_pair(x,y));
        cin>>b;
        rep(i,b){
            cin>>c>>d,c--,d--,con[c][d]=con[d][c]=1;
            if(find(c)!=find(d)){
                if(DBG)printf("insert %d %d\n",c+1,d+1);
                merge(c,d),E++;
            }
        }
        getDis();
        getNum();
    }
}