PKU 2488 TOJ 1702 A Knight's Journey 解题

 

 1#include<stdio.h>
 2#include<string.h>
 3int P[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
 4struct C{int r,l;};
 5C Q[30];
 6char use[30][30];
 7int p,q,K,ans,f;
 8void di(int a,int b)
 9{
10    if(K==ans)f=1;
11    if(f)return;
12    int i,r,l;
13    for(i=0;i<8;i++)
14    {
15        r=a+P[i][0];
16        l=b+P[i][1];
17        if(r>=1 && r<=&& l>=1 && l<=&& use[r][l])
18        {
19            K++;
20            use[r][l]=0;Q[K].l=l;Q[K].r=r;
21            //if(K==ans){f=1;return;}
22            di(r,l);
23            if(f)return;
24            use[r][l]=1;
25            K--;
26        }

27    }

28            
29}

30int main()
31{
32    int i,Kase,l;
33    scanf("%d",&Kase);
34    l=0;
35    while(l<Kase)
36    {
37        memset(use,1,sizeof(use));
38        memset(Q,0,sizeof(Q));
39        scanf("%d%d",&q,&p);
40        ans=p*q;
41        K=1;f=0;
42        Q[K].l=1;Q[K].r=1;
43        use[1][1]=0;
44        di(1,1);
45        printf("Scenario #%d:\n",++l);
46        if(!f)printf("impossible\n\n");
47        else
48        {
49            for(i=1;i<=ans;i++)printf("%c%c",Q[i].r+'A'-1,Q[i].l+'0');
50            printf("\n\n");
51        }

52    }

53    return 0
54
55}

56

深度优先搜索。
因为需要便利整个棋盘有要求遍历的顺序字典序最小。
那么可以确定深搜的顺序就是从A1开始的。
由于p*q<=26当期中一个为2的时候另一个大于10的时候肯定是不能遍历的。
所以不需要考虑B11 B9等一类出现时候字典序的问题了

posted @ 2008-07-15 19:31 gong 阅读(264) | 评论 (0)编辑 收藏

TOJ 2232 A Friendly Game 解题

题目很有意思。
女生找男朋友的问题。
以天津大学为背景,表现出男生比女生多的这个问题。
解决方法就是一个简单的dp问题了。
data[i][j]表示还剩下i个女生j个男生。
状态转移方程
data[i][j]=max{data[i][j-1],data[i-1][j-1]+map[i][j]};

 1#include<stdio.h>
 2//#define int long long 
 3int data[600][600];
 4int map[600][600];
 5#define oo -2000000001
 6void di(int i,int j)
 7{
 8    int max;
 9    if(i==0)
10    {
11        data[i][j]=0;
12        return;
13    }

14    if(i>j)
15    {
16        data[i][j]=oo-1;
17        return;
18    }

19    max=oo-1;
20    if(i-1>=0 && j-1>=0)
21    {
22        if(data[i-1][j-1]==oo)di(i-1,j-1);
23        if(data[i-1][j-1]+map[i][j]>max)
24            max=data[i-1][j-1]+map[i][j];
25    }

26    if(j-1>=0)
27    {
28        if(data[i][j-1]==oo)di(i,j-1);
29        if(data[i][j-1]>max)
30            max=data[i][j-1];
31    }

32    data[i][j]=max;
33    return;
34
35}

36int main()
37{
38    int i,j,n,m;
39    while(scanf("%d%d",&n,&m))
40    {
41        if(n==0 && m==0)break;
42        for(i=1;i<=n;i++)
43            for(j=1;j<=m;j++)scanf("%d",&map[i][j]);
44        for(i=0;i<=n;i++)
45            for(j=0;j<=m;j++)data[i][j]=oo;
46        di(n,m);
47        printf("%d\n",data[n][m]);
48    }

49    return 0;
50}

51


 

posted @ 2008-07-15 19:28 gong 阅读(112) | 评论 (0)编辑 收藏

TOJ 2236 Partial Sums 解题

组合数学问题
处理之前先对整个队列求一个和;
然后对每一个部分和统计一下
 1#include <stdio.h>
 2#include <string.h>
 3
 4int seq[100100];
 5int md[6000];
 6
 7long long jx(long long x) {
 8    return x*(x+1)/2;
 9}

10int main() {
11    int n, l, u;
12    int i;
13    int sum, m;
14    long long res, now, best;
15
16    while(scanf("%d%d%d"&n, &l, &u)!=EOF) {
17        for(i=0; i<n; i++{
18            scanf("%d"&seq[i]);
19        }

20        best = (long long)-1;
21        for(m=l; m<=u; m++{
22            memset(md, 0sizeof(md));
23            md[0= 1;
24            sum = 0;
25            for(i=0; i<n; i++{
26                sum = (sum+seq[i])%m;
27                md[sum] ++;
28            }

29            now = 0;
30            for(i=0; i<m; i++{
31                now += jx((long long)(md[i]-1));
32            }

33            //printf("%d: %I64d\n", m, now);
34            if(now > best) {
35                best = now;
36                res = m;
37            }

38        }

39        printf("%d\n", res);
40    }

41    return 0;
42}

43
44

posted @ 2008-07-15 19:24 gong 阅读(145) | 评论 (0)编辑 收藏

TOJ 2234 A+B In the Future 解题

就是高精度的题目
用java做比较简洁
 1import java.util.*;
 2import java.math.*;
 3
 4public class Main {
 5
 6   public static void main (String[] args) {
 7       Scanner cin=new Scanner (System.in);
 8    while (cin.hasNext())
 9    {
10        String ysa;
11        String ysb;
12        String sa=cin.next();
13        if (sa.charAt(0)=='+')
14            ysa=sa.substring(1);
15        else
16            ysa=sa;
17            
18        BigInteger a=new BigInteger(ysa,16);
19        String sb=cin.next();
20        if (sb.charAt(0)=='+')
21            ysb=sb.substring(1);
22        else
23            ysb=sb;
24        BigInteger b=new BigInteger(ysb,16);
25        
26        if (a.compareTo(b)==0 && a.compareTo(BigInteger.ZERO)==0)
27            break;
28        if (a.compareTo(b)< 0)
29            System.out.println(sa+" "+sb);
30        else
31            System.out.println(sb+" "+sa);
32        BigInteger ans=a.add(b);
33        if (ans.signum()>=0)
34            System.out.print('+');
35        System.out.println(ans.toString(16).toUpperCase());
36      
37    }

38 
39    }

40}
    
41

posted @ 2008-07-15 19:21 gong 阅读(131) | 评论 (0)编辑 收藏

TOJ 1075 Stockbroker Grapevine 解题

最短路径问题。
用Floyd-Warshall算法就好。
#include<stdio.h>
#include
<string.h>
int map[110][110];
int main()
{
    
int n,i,j,k,m,s,t,best,ans,a,b,max;
    
while(scanf("%d",&n),n)
    
{
        memset(map,
3,sizeof(map));
    
//    printf("%d",map[0][0]);
        for(i=1;i<=n;i++)
        
{
            scanf(
"%d",&m);
            
for(j=0;j<m;j++)
            
{
                scanf(
"%d%d",&a,&b);
                map[i][a]
=b;
            }

        }

/*
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
                printf("%d ",map[i][j]);
            printf("\n");
        }
*/

            
for(k=1;k<=n;k++)
                
for(s=1;s<=n;s++)
                    
for(t=1;t<=n;t++)
                        
if(map[s][t]>map[s][k]+map[k][t])
                            map[s][t]
=map[s][k]+map[k][t];
            best
=map[0][0];ans=0;
            
for(i=1;i<=n;i++)
            
{
                max
=0;
                
for(j=1;j<=n;j++)if(i!=&& map[i][j]>max)max=map[i][j];
                
//printf("***%d\n",max);
                if(max < best)
                
{
                    best 
= max;
                    ans
=i;
                }

            }

            
if(best!=map[0][0])printf("%d %d\n",ans,best);
            
else printf("disjoint\n");
    }

    
return 0;
}



posted @ 2008-07-15 19:19 gong 阅读(142) | 评论 (0)编辑 收藏

TOJ 1073 Smith Numbers 解题报告

 

 1#include<stdio.h>
 2#include<string.h>
 3char a[40010];
 4int b[5000],c[5000];
 5int main()
 6{
 7    int i, j, n, t, l1, l2,f;
 8    memset(a, 1sizeof(a));
 9    memset(b, 0sizeof(b));
10    for(i = 2;i <= 200;i++)
11      if(a[i])
12      {
13          t = 40000/i;
14          for(j = 2;j <= t;j++) a[i * j] = 0;
15      }

16    t = 0;
17    for(i = 2;i <= 40000;i++)
18      if(a[i])
19      {
20          b[t] = i;
21          n=i;
22          c[t]=0;
23          while(n)
24          {
25             c[t]+=n%10;
26             n/=10;
27          }
    
28          t++;
29      }

30    //printf("%d\n",c[0]);
31    while(scanf("%d",&n),n)
32    {
33        while(n++)
34        {
35        i=0;f=0;
36        while(b[i]*b[i]<=n)
37        {
38            if(n%b[i++]==0){f=1;break;}
39        }

40        if(f==0)continue;
41        i=0;t=n;l1=0;l2=0;
42        while(t)
43        {
44            l1+=t%10;
45            t/=10;
46        }

47        t=n;i=0;
48        while(b[i]*b[i]<=t)
49        {
50            while(t && t%b[i]==0)
51            {
52                l2+=c[i];
53                t/=b[i];
54            }

55            i++;
56        }

57    //    printf("%d %d\n",t,n);
58        if(t>1)
59        while(t)
60        {
61            l2+=t%10;
62            t/=10;
63        }

64        //printf("%d %d %d\n",n,l1,l2);
65        if(l1==l2)break;
66        }

67        printf("%d\n",n);
68    }

69    return 0;
70}

71
72

先把20000以内的质数都求出来
然后枚举每一个数把它变成质数的和然后把那个数字自己也拆分就可以了就是一个简单的枚举和模拟。

posted @ 2008-07-15 19:16 gong 阅读(198) | 评论 (0)编辑 收藏

TOJ 1070 Ouroboros Snake 解题

方法感觉写起来有点像宽搜。
就是每次生成就好了
 1#include<stdio.h>
 2#include<string.h>
 3int s[33000],use[33000],now[33000],data[16][33000];
 4int n,n2,p,q,v,f,i,k;
 5int main()
 6{
 7    for(n=2;n<=15;n++)
 8    {
 9        n2=1<<n;
10        memset(use,0,sizeof(use));
11        p=q=0;
12        s[p++]=0;
13        while(p>0)
14        {
15            v=s[p-1];
16            for(f=0;f<2;f++)
17                if(!use[(v<<1)+f])break;
18                if(f>=2){now[q++]=v;p--;}
19                else
20                {
21                    use[(v<<1)+f]=1;
22                    s[p++= ((v<<1+ f ) & ((n2>>1-1);
23                }

24        }

25          for(int i=0;i<n2;i++
26          data[n][i]=(now[n2-i]<<1| (now[n2-i-1]);
27    }

28    data[1][0]=0;data[1][1]=1;
29    while(scanf("%d%d",&n,&k),n)printf("%d\n",data[n][k]);
30    return 0;
31}

32

posted @ 2008-07-15 19:13 gong 阅读(171) | 评论 (0)编辑 收藏

Toj 1069 Erdos Numbers 解题

这个题目就是一个bfs的问题。在数据读取上需要稍加处理。
toj和poj的数据都有一个不是很符合规矩然后造成我这个题re了好多次。
期中有一个数据在最后一个人名结束后跟着一个空格然后是:这样我每次读取判断最后一个是:结束就错了
  1#include<vector>
  2#include<map>
  3#include<iostream>
  4#include<string>
  5#include<string.h>
  6using namespace std;
  7struct C{int p,ans;};
  8vector<int> data[11000];
  9map<string,int> name;
 10int use[11000];
 11C Q[11000];
 12char str[300];
 13int paper[300];
 14string a,b;
 15int main()
 16{
 17    int n,m,l=0,i,head,tail,L,l1,NO,j,f,KASE=0;
 18    //freopen("erdos.in","r",stdin);
 19    //freopen("erdos.txt","w",stdout);
 20    string nn;
 21    nn="Erdos*P.";
 22    while(1){
 23    scanf("%d%d",&n,&m);
 24    if(n==0&&m==0)break;
 25    l=0;
 26    for(i=0;i<10000;i++)data[i].clear();
 27    name.clear();
 28    memset(use,-1,sizeof(use));
 29    memset(Q,0,sizeof(Q));
 30    l=0;
 31    while(n--)
 32    {
 33        f=0;NO=0;
 34        while(1)
 35        {
 36            scanf("%s",str);
 37            l1=strlen(str);
 38            str[l1-1]='*';
 39            a=str;
 40            scanf("%s",str);
 41            l1=strlen(str);
 42            if(str[l1-1]==':')f=1;
 43            if(str[l1-1]=='.')f=1;
 44            str[l1-1]=0;
 45            a=a+str;
 46            if(name.count(a)==0)
 47            {
 48                name[a]=l++;
 49                //cout << a << endl;
 50            }

 51            paper[NO++]=name[a];
 52            if(f)
 53            {
 54                gets(str);
 55                //str=getline();
 56                break;
 57            }

 58        }

 59        
 60        for(i=0;i<NO;i++)
 61            for(j=0;j<NO;j++)if(i!=j)data[paper[i]].push_back(paper[j]);
 62    }

 63    if(name.count(nn)==0)name[nn]=l++;
 64    Q[0].p=name[nn];
 65    Q[0].ans=0;
 66    use[name[nn]]=0;
 67    head=tail=0;
 68    tail++;
 69    while(head!=tail)
 70    {
 71        L=Q[head].p;
 72        l=data[L].size();
 73        for(i=0;i<l;i++)
 74            if(use[data[L][i]]==-1)
 75            {
 76                use[data[L][i]]=Q[head].ans+1;
 77                Q[tail].p=data[L][i];
 78                Q[tail++].ans=Q[head].ans+1;
 79            }
    
 80        head++;
 81    }

 82    printf("Database #%d\n",++KASE);
 83    while(m--)
 84    {
 85            
 86            scanf("%s",str);
 87            printf("%s ",str);
 88            l1=strlen(str);
 89            str[l1-1]='*';
 90            a=str;
 91            scanf("%s",str);
 92            printf("%s: ",str);
 93            a=a+str;
 94            if(name.count(a)==0)printf("infinity\n");
 95            else if(use[name[a]]==-1)printf("infinity\n");
 96            else printf("%d\n",use[name[a]]);
 97    }

 98    printf("\n");
 99    }

100    return 0;
101}

102
103
104

posted @ 2008-07-15 19:09 gong 阅读(305) | 评论 (0)编辑 收藏

ACM中使用JAVA的介绍

Chapter I.

Java的优缺点各种书上都有,这里只说说用Java做ACM-ICPC的特点:

(1) 最明显的好处是,学会Java,可以参加Java Challenge   :)
(2) 对于熟悉C/C++的程序员来说,Java 并不难学,找本书,一两周业余时间就可以搞定了。当然,这里只是指一般编程,想熟悉所有的Java库还是需要些时间的。
     事实上,Java 只相当于C++的一个改进版,所有的语法都几乎是C++的,很少有变动。
(3) 在一般比赛中,Java程序会有额外的时间和空间,而实际上经过实验,在执行计算密集任务的时候Java并不比C/C++慢多少,只是IO操作较慢而已。
(4) Java 简单而功能强大,有些东西用Java实现起来更为方便,比如高精度。
(5) 用Java不易犯细微的错误,比如C/C++中的指针, “if (n = m) ... ” 等
(6) 目前来看Eclipse已成基本配置,写Java程序反而比C/C++更方便调试。在具体竞赛时也算多一种选择。
(7) 学会Java对以后工作有好处。现在国外很多地方会Java的人比会C/C++的人多。
(8) 会Java可以使你看起来更像偶蹄类动物(牛)     hoho~


Chapter II.

下面说一下ACM-ICPC队员初用Java编程所遇到的一些问题:

1. 基本输入输出:

(1)
JDK 1.5.0 新增的Scanner类为输入提供了良好的基础,简直就是为ACM-ICPC而设的。

一般用法为:

import java.io.*
import java.util.*

public class Main
{
     public static void main(String args[])
     {
         Scanner cin = new Scanner(new BufferedInputStream(System.in));
         ...
     }
}

当然也可以直接 Scanner cin = new Scanner(System.in);
只是加Buffer可能会快一些

(2)
读一个整数:   int n = cin.nextInt();         相当于   scanf("%d", &n);   或 cin >> n;
读一个字符串:String s = cin.next();         相当于   scanf("%s", s);     或 cin >> s;
读一个浮点数:double t = cin.nextDouble();   相当于   scanf("%lf", &t); 或 cin >> t;
读一整行:     String s = cin.nextLine();     相当于   gets(s);           或 cin.getline(...);
判断是否有下一个输入可以用 cin.hasNext() 或 cin.hasNextInt() 或 cin.hasNextDouble() 等,具体见 TOJ 1001 例程。

(3)
输出一般可以直接用 System.out.print() 和 System.out.println(),前者不输出换行,而后者输出。
比如:System.out.println(n);   // n 为 int 型
同一行输出多个整数可以用
     System.out.println(new Integer(n).toString() + " " + new Integer(m).toString());

也可重新定义:

static PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));
cout.println(n);

(4)
对于输出浮点数保留几位小数的问题,可以使用DecimalFormat类,

import java.text.*;
DecimalFormat f = new DecimalFormat("#.00#");
DecimalFormat g = new DecimalFormat("0.000");
double a = 123.45678, b = 0.12;
System.out.println(f.format(a));
System.out.println(f.format(b));
System.out.println(g.format(b));

这里0指一位数字,#指除0以外的数字。


2. 大数字

BigInteger 和 BigDecimal 是在java.math包中已有的类,前者表示整数,后者表示浮点数

用法:
不能直接用符号如+、-来使用大数字,例如:

(import java.math.*)   // 需要引入 java.math 包

BigInteger a = BigInteger.valueOf(100);
BigInteger b = BigInteger.valueOf(50);
BigInteger c = a.add(b)   // c = a + b;

主要有以下方法可以使用:
BigInteger add(BigInteger other)
BigInteger subtract(BigInteger other)
BigInteger multiply(BigInteger other)
BigInteger divide(BigInteger other)
BigInteger mod(BigInteger other)
int compareTo(BigInteger other)
static BigInteger valueOf(long x)

输出大数字时直接使用 System.out.println(a) 即可。


3. 字符串

String 类用来存储字符串,可以用charAt方法来取出其中某一字节,计数从0开始:

String a = "Hello";     // a.charAt(1) = ’e’

用substring方法可得到子串,如上例

System.out.println(a.substring(0, 4))     // output "Hell"

注意第2个参数位置上的字符不包括进来。这样做使得 s.substring(a, b) 总是有 b-a个字符。

字符串连接可以直接用 + 号,如

String a = "Hello";
String b = "world";
System.out.println(a + ", " + b + "!");     // output "Hello, world!"

如想直接将字符串中的某字节改变,可以使用另外的StringBuffer类。


4. 调用递归(或其他动态方法)

在主类中 main 方法必须是 public static void 的,在 main 中调用非static类时会有警告信息,
可以先建立对象,然后通过对象调用方法:

public class Main
{
     ...

     void dfs(int a)
     {
         if (...) return;
         ...
         dfs(a+1);
     }
    
     public static void main(String args[])
     {
         ...
         Main e = new Main();
         e.dfs(0);
         ...
     }
}

5. 其他注意的事项

(1) Java 是面向对象的语言,思考方法需要变换一下,里面的函数统称为方法,不要搞错。

(2) Java 里的数组有些变动,多维数组的内部其实都是指针,所以Java不支持fill多维数组。
     数组定义后必须初始化,如 int[] a = new int[100];

(3) 布尔类型为 boolean,只有true和false二值,在 if (...) / while (...) 等语句的条件中必须为boolean类型。
     在C/C++中的 if (n % 2) ... 在Java中无法编译通过。

(4) 下面在java.util包里Arrays类的几个方法可替代C/C++里的memset、qsort/sort 和 bsearch:

Arrays.fill()
Arrays.sort()
Arrays.binarySearch() 

posted @ 2008-07-15 19:02 gong 阅读(159) | 评论 (0)编辑 收藏

Toj 2248 Channel Design 解题报告

     摘要: 【题意分析】 给一个有向图求最小生成树。由于是有向图所以prim和kruskal是不能解决的。这里涉及到一个求有向图最小生成树的算法叫做最小树形图。 【算法分析】 1.把这个图消去自环 2.给除了根以外的每个点找到一个最小的入边 3.如果这个最小入边集中不含有向环的话我们就可以证明这个集合就是该图的最小生成树了。 4.如果存在有向环的话,我们就将这个有向环整体看做一个顶点,同时改变图中...  阅读全文

posted @ 2008-07-15 12:36 gong 阅读(177) | 评论 (0)编辑 收藏

仅列出标题
共5页: 1 2 3 4 5 
<2024年7月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿(6)

随笔档案

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜