2012年9月20日 星期四

uva 10344 - 23 Out of 5


Problem I
23 Out of 5
Input: standard input
Output: standard output
Time Limit: 1 second
Memory Limit: 32 MB
Your task is to write a program that can decide whether you can find an arithmetic expression consisting of five given numbers (1<=i<=5) that will yield the value 23.
For this problem we will only consider arithmetic expressions of the following from:
 
where : {1,2,3,4,5} -> {1,2,3,4,5} is a bijective function
and  {+,-,*} (1<=i<=4)

Input

The Input consists of 5-Tupels of positive Integers, each between 1 and 50.
Input is terminated by a line containing five zero's. This line should not be processed.

Output

For each 5-Tupel print "Possible" (without quotes) if their exists an arithmetic expression (as described above) that yields 23. Otherwise print "Impossible".

Sample Input

1 1 1 1 1
1 2 3 4 5
2 3 5 7 11
0 0 0 0 0

Sample Output

Impossible
Possible
Possible

Thomas Strohmann

DFS +backtracking


#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#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 data[5];
bool used[5];
bool DFS(int ind,int num,int len,int left){
if(DBG)printf("dfs: ind num %d %d\n",ind,num);
int b;
if(len==5)return num==23;
if(num-23>left){if(DBG)printf("len num left %d %d %d\n",len,num,left);return 0;}
used[ind]=1;
rep(i,5){
if(!used[i]){
b=left-data[i];
if(DFS(i,num+data[i],len+1,b))return 1;
if(DFS(i,num-data[i],len+1,b))return 1;
if(DFS(i,num*data[i],len+1,b))return 1;
}
}
used[ind]=0;
return 0;
}
void ans(){
int tot=0;
rep(i,5)tot+=data[i];
memset(used,0,sizeof(used));
rep(i,5)if(DFS(i,data[i],1,tot-data[i])){printf("Possible\n");return;}
printf("Impossible\n");
}
int main(){
int a,i;
while(scanf("%d%d%d%d%d",&data[0],&data[1],&data[2],&data[3],&data[4])==5){
for(i=0;i<5;i++)if(data[i]>0)break;
if(i==5)break;
ans();
}
}

10285 - Longest Run on a Snowboard


Problem C
Longest Run on a Snowboard
Input: standard input
Output: standard output
Time Limit: 5 seconds
Memory Limit: 32 MB

Michael likes snowboarding. That's not very surprising, since snowboarding is really great. The bad thing is that in order to gain speed, the area must slide downwards. Another disadvantage is that when you've reached the bottom of the hill you have to walk up again or wait for the ski-lift.
Michael would like to know how long the longest run in an area is. That area is given by a grid of numbers, defining the heights at those points. Look at this example:
 1  2  3  4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
One can slide down from one point to a connected other one if and only if the height decreases. One point is connected to another if it's at left, at right, above or below it. In the sample map, a possible slide would be 24-17-16-1 (start at 24, end at1). Of course if you would go 25-24-23-...-3-2-1, it would be a much longer run. In fact, it's the longest possible.
Input
The first line contains the number of test cases N. Each test case starts with a line containing the name (it's a single string), the number of rows R and the number of columns C. After that follow R lines with C numbers each, defining the heights.R and C won't be bigger than 100, N not bigger than 15 and the heights are always in the range from 0 to 100.
For each test case, print a line containing the name of the area, a colon, a space and the length of the longest run one can slide down in that area.
Sample Input
2
Feldberg 10 5
56 14 51 58 88
26 94 24 39 41
24 16 8 51 51
76 72 77 43 10
38 50 59 84 81
5 23 37 71 77
96 10 93 53 82
94 15 96 69 9
74 0 62 38 96
37 54 55 82 38
Spiral 5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

Sample Output
Feldberg: 7
Spiral: 25

(Math Lovers’ Contest, Problem Setter: Stefan Pochmann)

DFS + backtracking

#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#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;

//bool trav[10000];
int LM,R,C;
int maz[100][100],num[100][100],dir[4][2];
bool trav[100][100];
void init(){
    dir[0][0]=-1,dir[1][1]=-1,dir[2][0]=1,dir[3][1]=1;
}
bool isValid(int a,int b){return a>=0&&a<R&&b>=0&&b<C;}
void DFS(int r,int c,int len){
    trav[r][c]=1;
    if(len>LM)LM=len;
    if(len>num[r][c])num[r][c]=len;
    int a,b;
    rep(i,4){
        a=r+dir[i][0],b=c+dir[i][1];
        if(isValid(a,b)&&maz[a][b]<maz[r][c]&&!trav[a][b]&&len+1>num[a][b]){
            DFS(a,b,len+1);
        }
    }
    trav[r][c]=0;
}
void ans(){
    memset(num,0,sizeof(num)),LM=0;
    rep(i,R)rep(j,C){
        DFS(i,j,1);
    }
    printf("%d\n",LM);
}
int main(){
    int n;
    char name[1000];
    init();
    scanf("%d",&n);
    rep(i,n){
        scanf("%s%d%d",name,&R,&C);
        rep(i,R)rep(j,C)scanf("%d",&maz[i][j]);
        printf("%s: ",name);
        ans();
    }
}

uva 10276 - Hanoi Tower Troubles Again!

Problem H
Hanoi Tower Troubles Again!
Input: Standard Input
Output: Standard Output
People stopped moving discs from peg to peg after they know the number of steps needed to complete the entire task. But on the other hand, they didn't not stopped thinking about similar puzzles with the Hanoi Tower. Mr.S invented a little game on it. The game consists of N pegs and a LOT of balls. The balls are numbered 1,2,3... The balls look ordinary, but they are actually magic. If the sum of the numbers on two balls is NOT a square number, they will push each other with a great force when they're too closed, so they can NEVER be put together touching each other.

The player should place one ball on the top of a peg at a time. He should first try ball 1, then ball 2, then ball 3... If he fails to do so, the game ends. Help the player to place as many balls as possible. You may take a look at the picture above, since it shows us a best result for 4 pegs.
Input
The first line of the input contains a single integer T, indicating the number of test cases. (1<=T<=50) Each test case contains a single integer N(1<=N<=50), indicating the number of pegs available.
Output
For each test case in the input print a line containing an integer indicating the maximal number of balls that can be placed. Print -1 if an infinite number of balls can be placed.
Sample Input
2
4
25
Sample Output
11
337
__________________________________________________________________________________________
Rujia Liu


DFS, O(1) solution exists here 

#include<stdio.h>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#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;

//bool trav[10000];
int LM,N;
int top[50];
bool isSqr(int c){
int a=int(sqrt(c));
return a*a==c;
}
void DFS(int cur,int len){
if(cur-1>LM)LM=cur-1;
int b;
rep(i,min(len+1,N)){
if(cur>LM-N&&(isSqr(top[i]+cur)||top[i]==0)){
if(DBG)printf("LM-N top cur loc %d %d %d %d\n",LM-N, top[i],cur,i);
b=top[i],top[i]=cur;
DFS(cur+1,min(max(i+2,len),N));
top[i]=b;
}
}
}
void ans(){
LM=0;
DFS(1,1);
printf("%d\n",LM);
}
int main(){
int n;
scanf("%d",&n);
rep(i,n)scanf("%d",&N),ans();
}

uva 10067 - Playing with Wheels


Problem C
Playing with Wheels
Input: standard Input
Output: standard output

In this problem we will be considering a game played with four wheels. Digits ranging from 0 to 9 are printed consecutively (clockwise) on the periphery of each wheel. The topmost digits of the wheels form a four-digit integer. For example, in the following figure the wheels form the integer 8056. Each wheel has two buttons associated with it. Pressing the button marked with a left arrow rotates the wheel one digit in the clockwise direction and pressing the one marked with the right arrow rotates it by one digit in the opposite direction.

                
The game starts with an initial configuration of the wheels. Say, in the initial configuration the topmost digits form the integer S1S2S3S4. You will be given some (say, n) forbidden configurations Fi1Fi2Fi3Fi4  (1 <= i <= n ) and a target configuration T1T2T3T4. Your job will be to write a program that can calculate the minimum number of button presses required to transform the initial configuration to the target configuration by never passing through a forbidden one.

Input
The first line of the input contains an integer N giving the number of test cases to follow.
The first line of each test case contains the initial configuration of the wheels specified by 4 digits. Two consecutive digits are separated by a space. The next line contains the target configuration. The third line contains an integer n giving the number of forbidden configurations. Each of the following n lines contains a forbidden configuration.
There is a blank line between two consecutive input sets.
           
Output
For each test case in the input print a line containing the minimum number of button presses required. If the target configuration is not reachable then print -1.

Sample Input
2
8 0 5 6
6 5 0 8
5
8 0 5 7
8 0 4 7
5 5 0 8
7 5 0 8
6 4 0 8

0 0 0 0
5 3 1 7
8
0 0 0 1
0 0 0 9
0 0 1 0
0 0 9 0
0 1 0 0
0 9 0 0
1 0 0 0
9 0 0 0

Sample Output
14
-1
______________________________________________________________________________________
Rezaul Alam Chowdhury


BFS

#include<stdio.h>
#include<cstring>
#include<string>
#include<queue>
#include<set>
#include<vector>
#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;

bool trav[10000];
int start[4],csn[4],end;
set<int>forbid;
void getCN(int a){
int i=3;
memset(csn,0,sizeof(csn));
while(a>0)csn[i--]=a%10,a/=10;
}
int getN(){
return csn[0]*1000+csn[1]*100+csn[2]*10+csn[3];
}
void ans(){
memcpy(csn,start,sizeof(start));
memset(trav,0,sizeof(trav));
queue<pair<int,int> >q;
int cur,res=-1,dis,b,next;
cur=getN();
trav[cur]=1;
q.push(make_pair(cur,0));
while(q.size()){
cur=q.front().first,dis=q.front().second;q.pop();
if(DBG)printf("cur dis %d %d\n",cur,dis);
if(cur==end){res=dis;break;}
getCN(cur);
rep(i,4){
b=csn[i],csn[i]=(csn[i]+1)%10;
next=getN();
if(!trav[next]&&!forbid.count(next))trav[next]=1,q.push(make_pair(next,dis+1));
csn[i]=b,csn[i]=((csn[i]-1)<0?9:(csn[i]-1));
next=getN();
if(!trav[next]&&!forbid.count(next))trav[next]=1,q.push(make_pair(next,dis+1));
csn[i]=b;
}
}
printf("%d\n",res);
}
int main(){
int n,a,b,c,d,e;
scanf("%d",&n);
rep(i,n){
forbid.clear();
scanf("%d%d%d%d",&start[0],&start[1],&start[2],&start[3]);
scanf("%d%d%d%d",&a,&b,&c,&d),end=a*1000+b*100+c*10+d;
scanf("%d",&a);
rep(i,a){
scanf("%d%d%d%d",&b,&c,&d,&e);
forbid.insert(b*1000+c*100+d*10+e);
}
ans();
}
}

2012年9月19日 星期三

uva 539 - The Settlers of Catan



  The Settlers of Catan 

Within Settlers of Catan, the 1995 German game of the year, players attempt to dominate an island by building roads, settlements and cities across its uncharted wilderness.
You are employed by a software company that just has decided to develop a computer version of this game, and you are chosen to implement one of the game's special rules:


When the game ends, the player who built the longest road gains two extra victory points.


The problem here is that the players usually build complex road networks and not just one linear path. Therefore, determining the longest road is not trivial (although human players usually see it immediately).


Compared to the original game, we will solve a simplified problem here: You are given a set of nodes (cities) and a set of edges (road segments) of length 1 connecting the nodes. The longest road is defined as the longest path within the network that doesn't use an edge twice. Nodes may be visited more than once, though.


Example: The following network contains a road of length 12.

o        o -- o        o
 \      /      \      /
  o -- o        o -- o
 /      \      /      \
o        o -- o        o -- o
               \      /
                o -- o

Input 

The input file will contain one or more test cases.The first line of each test case contains two integers: the number of nodes n ( $2 \le n \le 25$) and the number of edges m ($1 \le m \le 25$). The next m lines describe the m edges. Each edge is given by the numbers of the two nodes connected by it. Nodes are numbered from 0 to n-1. Edges are undirected. Nodes have degrees of three or less. The network is not neccessarily connected.
Input will be terminated by two values of 0 for n and m.

Output 

For each test case, print the length of the longest road on a single line.

Sample Input 


3 2
0 1
1 2
15 16
0 2
1 2
2 3
3 4
3 5
4 6
5 7
6 8
7 8
7 9
8 10
9 11
10 12
11 12
10 13
12 14
0 0

Sample Output 


2
12



Miguel A. Revilla
1999-01-11

DFS
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<string>
#include<ctime>
#include<vector>
#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,LM;
int deg[25];
bool trav[25][25];
vector<int>edge[25];
bool DFS(int cur,int len){
    if(!deg[cur])LM=max(len,LM);
    else{
        int b;
        rep(i,edge[cur].size()){
            b=edge[cur][i];
            if(!trav[cur][b]){
                trav[cur][b]=trav[b][cur]=1,deg[cur]--,deg[b]--;
                DFS(b,len+1);
                trav[cur][b]=trav[b][cur]=0,deg[cur]++,deg[b]++;
            }
        }
    }
}
void ans(){
    LM=0;
    rep(i,N)deg[i]=edge[i].size();
    rep(i,N)DFS(i,0);
    printf("%d\n",LM);
}
int main(){
    int a,b,M;
    while(scanf("%d%d",&N,&M)==2){
        if(N==0&&M==0)break;
        rep(i,25)edge[i].clear();
        rep(i,M)scanf("%d%d",&a,&b),edge[a].push_back(b),edge[b].push_back(a);
        ans();
    }
}

uva 529 - Addition Chains



  Addition Chains 

An addition chain for n is an integer sequence $<a_0, a_1, a_2, \dots, a_m>$ with the following four properties:

  • a0 = 1
  • am = n
  • a01
2<...m-1m
  • For each k ( $1 \le k \le m$) there exist two (not neccessarily different) integers i and j ( $0 \le i, j \le k-1$) with ak=ai +aj
  • You are given an integer n. Your job is to construct an addition chain for n with minimal length. If there is more than one such sequence, any one is acceptable.
    For example, <1> and <1> are both valid solutions when you are asked for an addition chain for 5.

    Input Specification 

    The input file will contain one or more test cases. Each test case consists of one line containing one integer n ($1 \le n \le 10000$). Input is terminated by a value of zero (0) for n.

    Output Specification 

    For each test case, print one line containing the required integer sequence. Separate the numbers by one blank.

    Hint: The problem is a little time-critical, so use proper break conditions where necessary to reduce the search space.

    Sample Input 

    5
    7
    12
    15
    77
    0
    

    Sample Output 

    1 2 4 5
    1 2 4 6 7
    1 2 4 8 12
    1 2 4 5 10 15
    1 2 4 8 9 17 34 68 77
    
    
    Iterative DFS + pruning 

    #include<stdio.h>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<ctime>
    #include<vector>
    #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,CM;
    int cnt[10001];
    bool has[10001];
    vector<int>mv,cv;
    void print(){
    bool ll=0;
    rep(i,mv.size()){if(ll)printf(" ");ll=1;printf("%d",mv[i]);}
    printf("\n");
    }
    bool DFS(int cur){
    if(DBG)printf("dfs cur %d size %d\n",cur, cv.size());
    if(cur==N){mv=cv;return 1;}
    else{
    int c,bc,k,j;
    has[cur]=1;
    rep(i,cv.size()){
    c=cur+cv[i];
    for(k=c,j=cv.size()+2;j<CM+1;k*=2,j++);
    if(k<N)continue;
    if(c<=N&&!has[c]&&cv.size()+1<=cnt[c]){
    cnt[c]=cv.size()+1;
    cv.push_back(c);
    if(DFS(c))return 1;
    cv.pop_back();
    }
    }
    has[cur]=0;
    return 0;
    }

    }
    void init(){
    memset(cnt,0x7f,sizeof(cnt));
    }
    int getNum(int a){
    return int(ceil(log(a)/log(2)));
    }
    void ans(){
    memset(has,0,sizeof(has));
    cv.clear(),cv.push_back(1),CM=18,has[0]=1;
    if(DBG)printf("cur %d\n",N);
    int n=getNum(N);
    REP(i,n,19){
    mv.clear(),CM=i;
    DFS(1);
    if(mv.size())break;
    }
    print();
    }
    int main(){
    int a;
    init();
    while(scanf("%d",&N)==1){
    if(N==0)break;
    ans();
    }
    //int t=clock();
    //printf ("%f seconds.\n",((float)t)/CLOCKS_PER_SEC);
    }

    uva 524 - Prime Ring Problem



      Prime Ring Problem 

    A ring is composed of n (even number) circles as shown in diagram. Put natural numbers $1, 2, \dots, n$ into each circle separately, and the sum of numbers in two adjacent circles should be a prime.



    Note: the number of first circle should always be 1.

    Input 

    n (0 < n <= 16)

    Output 

    The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements.

    You are to write a program that completes above process.

    Sample Input 

    6
    8
    

    Sample Output 

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



    Miguel A. Revilla
    1999-01-11

    DFS
    #include<stdio.h>
    #include<cstring>
    #include<string>
    #include<vector>
    #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 cases=1,N;
    vector<int>res;
    bool notp[50];
    bool trav[16];
    void getP(){
    notp[0]=notp[1]=1;
    REP(i,2,50){
    if(!notp[i]){
    if(DBG)printf("p %d\n",i);
    for(int j=i*i;j<50;j+=i)notp[j]=1;
    }
    }
    }
    void print(){
    bool ll=0;
    rep(i,res.size()){if(ll)printf(" ");ll=1,printf("%d",res[i]);}printf("\n");
    }
    void DFS(int cur,int len){
    if(DBG)printf("len %d\n",len);
    if(len==N){if(DBG)printf("len %d: cur first %d %d\n",len,cur+1,res[0]);
    if(!notp[cur+1+res[0]])print();}
    else{
    trav[cur]=1;
    rep(i,N)
    if(!trav[i]&&!notp[cur+1+(i+1)]){
    if(DBG)printf("%d + %d is prime\n",cur+1,i+1);
    res.push_back(i+1);
    DFS(i,len+1);
    res.pop_back();
    }
    trav[cur]=0;
    }
    }
    void ans(){
    res.clear(),res.push_back(1);
    printf("Case %d:\n",cases++);
    DFS(0,1);
    }
    int main(){
    bool ll=0;
    getP();
    while(scanf("%d",&N)==1){
    if(ll)printf("\n");ll=1;
    ans();
    }
    }