HDU - 1166(线段树模板题.)、HDU - 1072(DFS.)、HDU - 1075(字典树.)

Time limit1000 ms
Memory limit32768 kB
OSWindows

题目:
C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。
中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的.
Input
第一行一个整数T,表示有T组数据。
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令
Output
对第i组数据,首先输出“Case i:”和回车,
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。
Sample Input
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
Sample Output
Case 1:
6
33
59

代码:

/*
HDU 1166  敌兵布阵

*/
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
using namespace std;
const int MAXN=50005;
struct Node
{
    int l,r;
    int nSum;
}segTree[MAXN*3];
int num[MAXN];
void Build(int i,int l,int r)
{
    segTree[i].l=l;
    segTree[i].r=r;
    if(l==r)
    {
        segTree[i].nSum=num[l];
        return;
    } 
    int mid=(l+r)>>1;
    Build(i<<1,l,mid);
    Build(i<<1|1,mid+1,r);
    segTree[i].nSum=segTree[i<<1].nSum+segTree[i<<1|1].nSum;   
}  
void Add(int i,int t,int b)
{
    segTree[i].nSum+=b;
    if(segTree[i].l==t&&segTree[i].r==t)   return;
    int mid=(segTree[i].l+segTree[i].r)>>1;
    if(t<=mid)  Add(i<<1,t,b);
    else       Add(i<<1|1,t,b);
}    
int Query(int i,int l,int r)
{
    if(l==segTree[i].l&&r==segTree[i].r)
       return segTree[i].nSum;
    int mid=(segTree[i].l+segTree[i].r)>>1;
    if(r<=mid)  return Query(i<<1,l,r);
    else if(l>mid)   return Query(i<<1|1,l,r);
    else  return Query(i<<1,l,mid)+Query(i<<1|1,mid+1,r);
}    
int main()
{
    int T;
    int iCase=0;
    int n,i;
    char str[10];
    int a,b;
    scanf("%d",&T);
    while(T--)
    {
        iCase++;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
           scanf("%d",&num[i]);
        Build(1,1,n);
        printf("Case %d:\n",iCase);
        while(scanf("%s",&str))
        {
            if(strcmp(str,"End")==0) break;
            scanf("%d%d",&a,&b);
            if(strcmp(str,"Add")==0) Add(1,a,b);
            else if(strcmp(str,"Sub")==0)  Add(1,a,-b);
            else  printf("%d\n",Query(1,a,b));
        }    
    }
    return 0;    
}

Time limit 1000 ms
Memory limit 32768 kB
OS Windows

题目:
Ignatius had a nightmare last night. He found himself in a labyrinth with a time bomb on him. The labyrinth has an exit, Ignatius should get out of the labyrinth before the bomb explodes. The initial exploding time of the bomb is set to 6 minutes. To prevent the bomb from exploding by shake, Ignatius had to move slowly, that is to move from one area to the nearest area(that is, if Ignatius stands on (x,y) now, he could only on (x+1,y), (x-1,y), (x,y+1), or (x,y-1) in the next minute) takes him 1 minute. Some area in the labyrinth contains a Bomb-Reset-Equipment. They could reset the exploding time to 6 minutes.

Given the layout of the labyrinth and Ignatius’ start position, please tell Ignatius whether he could get out of the labyrinth, if he could, output the minimum time that he has to use to find the exit of the labyrinth, else output -1.

Here are some rules:

  1. We can assume the labyrinth is a 2 array.
  2. Each minute, Ignatius could only get to one of the nearest area, and he should not walk out of the border, of course he could not walk on a wall, too.
  3. If Ignatius get to the exit when the exploding time turns to 0, he can’t get out of the labyrinth.
  4. If Ignatius get to the area which contains Bomb-Rest-Equipment when the exploding time turns to 0, he can’t use the equipment to reset the bomb.
  5. A Bomb-Reset-Equipment can be used as many times as you wish, if it is needed, Ignatius can get to any areas in the labyrinth as many times as you wish.
  6. The time to reset the exploding time can be ignore, in other words, if Ignatius get to an area which contain Bomb-Rest-Equipment, and the exploding time is larger than 0, the exploding time would be reset to 6.
    Input
    The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
    Each test case starts with two integers N and M(1<=N,Mm=8) which indicate the size of the labyrinth. Then N lines follow, each line contains M integers. The array indicates the layout of the labyrinth.
    There are five integers which indicate the different type of area in the labyrinth:
    0: The area is a wall, Ignatius should not walk on it.
    1: The area contains nothing, Ignatius can walk on it.
    2: Ignatius’ start position, Ignatius starts his escape from this position.
    3: The exit of the labyrinth, Ignatius’ target position.
    4: The area contains a Bomb-Reset-Equipment, Ignatius can delay the exploding time by walking to these areas.
    Output
    For each test case, if Ignatius can get out of the labyrinth, you should output the minimum time he needs, else you should just output -1.
    Sample Input
    3
    3 3
    2 1 1
    1 1 0
    1 1 3
    4 8
    2 1 1 0 1 1 1 0
    1 0 4 1 1 0 4 1
    1 0 0 0 0 0 0 1
    1 1 1 4 1 1 1 3
    5 8
    1 2 1 1 1 1 1 4
    1 0 0 0 1 0 0 1
    1 4 1 0 1 1 0 1
    1 0 0 0 0 3 0 1
    1 1 4 1 1 1 1 1
    Sample Output
    4
    -1
    13

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
 
 
const int MAX = 9;
 
int dir[4][2]={1,0,-1,0,0,1,0,-1};
 
int map[MAX][MAX],step[MAX][MAX],time[MAX][MAX];
int n,m,sx,sy,dx,dy,minx;
 
void dfs(int x,int y,int len,int cnt){
	if(x<0 || y<0 || x>=n || y>=m)return;
	if(len<=0 || cnt>=minx)return;
	if(map[x][y]==0)return;
	if(map[x][y]==3){
		if(cnt<minx)minx=cnt;
		return;
	}
	if(map[x][y]==4){
		len=6;
	}
	//下面的这个剪枝很重要,不剪就会超时
	//从当前点x,y走到下一个可能点的距离大于从其他途径到tx,ty的距离,且到tx,ty点时的剩余时间大于由x,y点到tx,ty点后的剩余时间,就跳过
	//这是因为结点可重复访问所以本身没标记,那么当上述条件满足时,由tx,ty开始的最优解已经求过(存在或者不存在),所以不需要再重复求了。
	if(cnt>=step[x][y] && time[x][y]>=len)return;
	step[x][y]=cnt;
	time[x][y]=len;
	int tx,ty,i;
	for(i=0;i<4;++i){
		tx = x+dir[i][0];
		ty = y+dir[i][1];
		dfs(tx,ty,len-1,cnt+1);
	}
}
 
int main(){
 
	//freopen("in.txt","r",stdin);
	int t,i,j,len,cnt;
	scanf("%d",&t);
	while(t--){
		scanf("%d %d",&n,&m);
		for(i=0;i<n;++i){
			for(j=0;j<m;++j){
				time[i][j]=0;
				step[i][j]=INT_MAX-3;//这里置一个大数,表示到i,j的步数无限大
				scanf("%d",&map[i][j]);
				if(map[i][j]==2){
					sx = i;
					sy = j;
				}else if(map[i][j]==3){
					dx = i;
					dy = j;
				}
			}
		}
		len = 6;
		cnt = 0;
		minx = INT_MAX;
		dfs(sx,sy,len,cnt);
		if(minx==INT_MAX){
			printf("-1\n");
		}else{
			printf("%d\n",minx);
		}
	}
	
    return 0;
}

Time limit 5000 ms
Memory limit 204800 kB
OS Windows

题目:
Ignatius is so lucky that he met a Martian yesterday. But he didn’t know the language the Martians use. The Martian gives him a history book of Mars and a dictionary when it leaves. Now Ignatius want to translate the history book into English. Can you help him?
Input
The problem has only one test case, the test case consists of two parts, the dictionary part and the book part. The dictionary part starts with a single line contains a string “START”, this string should be ignored, then some lines follow, each line contains two strings, the first one is a word in English, the second one is the corresponding word in Martian’s language. A line with a single string “END” indicates the end of the directory part, and this string should be ignored. The book part starts with a single line contains a string “START”, this string should be ignored, then an article written in Martian’s language. You should translate the article into English with the dictionary. If you find the word in the dictionary you should translate it and write the new word into your translation, if you can’t find the word in the dictionary you do not have to translate it, and just copy the old word to your translation. Space(’ ‘), tab(’\t’), enter(’\n’) and all the punctuation should not be translated. A line with a single string “END” indicates the end of the book part, and that’s also the end of the input. All the words are in the lowercase, and each word will contain at most 10 characters, and each line will contain at most 3000 characters.
Output
In this problem, you have to output the translation of the history book.
Sample Input
START
from fiwo
hello difh
mars riwosf
earth fnnvk
like fiiwj
END
START
difh, i’m fiwo riwosf.
i fiiwj fnnvk!
END
Sample Output
hello, i’m from mars.
i like earth!

Hint
Huge input, scanf is recommended.

思路:
  将字典中的火星文单词,也就是右边的单词构造成一棵字典树。在单词结束的节点中存储其对应的英文翻译。输入的时候读取整行,然后遍历每一个字符,将所有字母连续的记录到一个字符数组中,直到遇到一个非英文字母的字符为止,这个时候从字典树中查找这个单词有没有对应的英文翻译,如果有,输出这个翻译,如果没有,输出原来的单词。

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
using namespace std;

struct Tire{
    Tire *next[26];
    char *trans;  //定义一个指向一维数组的指针
    Tire()  //构造函数
    {
        int i;
        for(i=0;i<26;i++){
            next[i]=NULL;
        }
        trans = NULL;
    }
};

Tire root;

void Insert(char trans[],char word[])   //将单词word插入到字典树中,并在最后加上翻译trans
{
    Tire *p = &root;
    int i;
    for(i=0;trans[i];i++){
        int n = trans[i]-'a';
        if(p->next[n]==NULL)
            p->next[n] = new Tire;
        p = p->next[n];
    }
    p->trans = (char*)malloc(sizeof(char)*11);
    strcpy(p->trans,word);
}
void Find(char str[])   //找到对应的翻译并输出,没找到则输出原来的字符串
{
    Tire *p = &root;
    int i;
    for(i=0;str[i];i++){
        int n = str[i]-'a';
        if(p->next[n]==NULL){
            printf("%s",str);
            return ;
        }
        p = p->next[n];
    }
    if(p->trans==NULL)
        printf("%s",str);
    else
        printf("%s",p->trans);
}

int main()
{
    char word[11],trans[11];
    scanf("%s",word);
    while(scanf("%s",word)!=EOF){   //输入字典
        if(strcmp(word,"END")==0)   //遇到结束标记
            break;
        scanf("%s",trans);
        Insert(trans,word); //将单词word插入到字典树中,并在最后加入其翻译
    }
    scanf("%s",word);
    getchar();
    char str[3001];
    while(gets(str)){
        if(strcmp(str,"END")==0)
            break;
        int i,j=0;
        char t[3001]={0};
        for(i=0;str[i];i++){
            if('a'<=str[i] && str[i]<='z'){ //检测到的是小写字母
                t[j++] = str[i];
            }
            else{
                t[j] = '\0';
                if(t[0]!='\0'){ //不是空的
                    Find(t);    //找到对应的翻译并输出,没找到则输出原来的字符串
                    t[0]='\0',j=0;  //初始化t
                }
                printf("%c",str[i]);
            }
        }
        printf("\n");
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43967023/article/details/86684899