HDU_Steps9.3 杂题 HDU2832 HDU2604 HDU1429 HDU2782 HDU1298 HDU2363 HDU3389 HDU1496

HDU2832 Snail’s trouble

100cm的绳子,蜗牛每分钟爬k cm,每分钟后绳子被拉长100cm,问多少分钟到终点

蜗牛第一分钟爬绳子的 k/100,第二分钟k/200...也就是求k/100*(1+1/2+1/3+..1/n)>=1的n的最小值

HDU2604 Queuing

一道递归,前面重复了,要用矩阵加速

HDU1429 胜利大逃亡(续)

在一般的迷宫上加了钥匙,必须拿了对应的钥匙才能开对应的门

BFS,状态有横竖坐标及在该点持有的钥匙组成,钥匙状态使用位运算来标记

#include<cstdio>
#include<queue>
#include<string.h>
using namespace std;
struct state{
	state(int a,int b,int d,int e){r=a,c=b,v=d,st=e;}
	int r,c,v,st;	
};
char map[30][30];
int n,m,t,stx,sty,mint;
int vis[30][30][1100];
int dr[]={1,0,-1,0},dc[]={0,1,0,-1};

int bfs(){
	memset(vis,0,sizeof vis);
	queue<state> q;
	q.push(state(stx,sty,0,0));
	vis[stx][sty][0]=1;
	
	while(!q.empty()){
		state os=q.front();q.pop();
		int r=os.r,c=os.c,v=os.v,st=os.st;//旧的状态参数
		for(int i=0;i<4;i++){
			int nr=r+dr[i],nc=c+dc[i],nv=v,nst=st+1;//新的状态参数	
			if(nst>=t||nr<0||nc<0||nr>=n||nc>=m||map[nr][nc]=='*')continue;//超出时间,范围,以及墙都是不可达位置
			char tc=map[nr][nc];
			if(tc=='^')return nst;//到达终点
			if(tc>='A'&&tc<='J'){//如果到了这个点却没有对应钥匙
				if((nv&(1<<(tc-'A')))==0)continue;	
			}else if(tc>='a'&&tc<='j'){//如果到的这个点有钥匙
				nv^=(1<<(tc-'a'));
			}
			if(!vis[nr][nc][nv]){//如果这个点未被访问过
				vis[nr][nc][nv]=1;
				q.push(state(nr,nc,nv,nst));	
			}

		}	
	}
	return -1;
}
int main(){
	while(scanf("%d%d%d",&n,&m,&t)!=EOF){
		for(int i=0;i<n;i++){
			scanf("%s",map[i]);	
			for(int j=0;j<m;j++){
				if(map[i][j]=='@')stx=i,sty=j;	
			}
		}
		printf("%d\n",bfs());
	}
	return 0;	
}


HDU2782 The Worm Turns

一个虫子只能一个方向吃到底,遇到墙或者吃过的地方转弯,使吃到的食物最多

真是敢搜就能过啊,程序写得烂,擦着时限的边过了。。

#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
int m,n,rs,a,b;
bool map[630][630];
int ans,tans,ansi,ansj,ansk;
int dr[]={0,-1,1,0},dc[]={1,0,0,-1};
bool canm(int nr,int nc){
    return nr>=0&&nc>=0&&nr<m&&nc<n&&map[nr][nc]==false;
}
bool flag;
void show(int st){
	printf("%d\n",st);
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			printf("%d",map[i][j]);	
		}	
		printf("\n");
	}	
	printf("\n");
}

void dfs(int nr,int nc,int d,int st){
	flag=false;
	if(canm(nr+dr[d],nc+dc[d])){
		flag=true;
		map[nr+dr[d]][nc+dc[d]]=true;
		dfs(nr+dr[d],nc+dc[d],d,st+1);
		map[nr+dr[d]][nc+dc[d]]=false;	
	}else{
		if(d==0||d==3){
			if(canm(nr+dr[1],nc+dc[1])){
				flag=true;
				map[nr+dr[1]][nc+dc[1]]=1;
				dfs(nr+dr[1],nc+dc[1],1,st+1);
				map[nr+dr[1]][nc+dc[1]]=0;	
			}
			if(canm(nr+dr[2],nc+dc[2])){
				flag=true;
				map[nr+dr[2]][nc+dc[2]]=1;
				dfs(nr+dr[2],nc+dc[2],2,st+1);
				map[nr+dr[2]][nc+dc[2]]=0;	
			}	
		}else{
			if(canm(nr+dr[0],nc+dc[0])){
				flag=true;
				map[nr+dr[0]][nc+dc[0]]=1;
				dfs(nr+dr[0],nc+dc[0],0,st+1);
				map[nr+dr[0]][nc+dc[0]]=0;	
			}
			if(canm(nr+dr[3],nc+dc[3])){
				flag=true;
				map[nr+dr[3]][nc+dc[3]]=1;
				dfs(nr+dr[3],nc+dc[3],3,st+1);
				map[nr+dr[3]][nc+dc[3]]=0;	
			}
		}		
	 }
	if(!flag)tans=tans>st?tans:st;
}
int main(){
    int cas=1;
    while(scanf("%d%d",&m,&n),m||n){
        memset(map,false,sizeof map);
        scanf("%d",&rs);
        for(int i=0;i<rs;i++){
            scanf("%d%d",&a,&b);
            map[a][b]=true;
        }
        ans=0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
				if(map[i][j])continue;
                for(int k=0;k<4;k++){
					tans=0;
                    map[i][j]=1;
                    if(canm(i+dr[k],j+dc[k]))dfs(i,j,k,1);
                    map[i][j]=0;
                    if(tans>ans){
                        ans=tans,ansi=i,ansj=j,ansk=k;    
                    }
                }
            }    
        }
        printf("Case %d: %d %d %d ",cas++,ans,ansi,ansj);
        if(ansk==0)printf("E\n");
        if(ansk==1)printf("N\n");
        if(ansk==2)printf("S\n");
        if(ansk==3)printf("W\n");
    }
    return 0;    
}


HDU1298 T9

字典树,不难。建字典树时对每一点有一个频度值,每次取这一层上频度最大的字母所在路径所组成的

#include<cstdio>
#include<string.h>
using namespace std;
struct trie{
	trie(){
		for(int i=0;i<26;i++)next[i]=NULL;
		pro=0;
	}
	trie *next[26];
	int pro;
}*root;
int cas,words,k;
char find[105],res[105],bres[105],wd[105];
int bpro;
bool flag;
//对应按键上的字母
int alpha[8][5]={{0,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}};
int alphas[8]={3,3,3,3,3,4,3,4};
void instrie(char *wd,int pro){
	int len=strlen(wd);
	trie *p=root;
	for(int i=0;i<len;i++){
		int t=wd[i]-'a';
		if(p->next[t]==NULL){
			p->next[t]=new trie;	
		}
		p=p->next[t];
		p->pro+=pro;//字典树上每一点的概率
	}
}
void dfs(int now,int len,trie *tr){
	if(now==len){//标记字典中右对应按键的结果并且选择最大概率的组合
		flag=true;
		if(tr->pro>bpro){
			bpro=tr->pro;	
			for(int i=0;i<now;i++){
				bres[i]=res[i];	
			}
			bres[now]='\0';
		}
		return;
	}
	int t=find[now]-'2';
	for(int i=0;i<alphas[t];i++){
		int r=alpha[t][i];
		if(tr->next[r]==NULL)continue;
		res[now]=r+'a';
		dfs(now+1,len,tr->next[r]);		
	}
	
}

int main(){
	int pro;
	scanf("%d",&cas);
	for(int ca=1;ca<=cas;ca++){
		printf("Scenario #%d:\n",ca);
		scanf("%d",&words);
		root=new trie;
		for(int i=0;i<words;i++){
			scanf("%s%d",wd,&pro);
			instrie(wd,pro);
		}
		scanf("%d",&k);
		while(k--){
			scanf("%s",find);
			int len=strlen(find);
			for(int i=1;i<len;i++){
				flag=false;
				bpro=0;
				dfs(0,i,root);
				if(flag){
					printf("%s\n",bres);
				}else{
					printf("MANUALLY\n");
				}
			}
			printf("\n");
		}
		printf("\n");
	}
	return 0;	
}


HDU2363 Cycling

其实就是枚举上下界的最短路,不难的一道题却WA了很久很久。。郁闷

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string.h>
#include<queue>
//枚举上下界求最短路
using namespace std;
const int inf=1000000000;
struct node{
    int v,i;
    node(int a,int b){v=a,i=b;}
    bool operator <(const node& n)const{
        return v>n.v;
    }    
};
struct ati{
    int l,h;
    bool operator<(const ati& a)const{
        return h-l<(a.h-a.l);    
    }    
}at[100004];
int cas,n,m,h[105],a,b,c;
int map[105][105];
int dij(int low,int high){
    int done[105];
    int d[105];
    for(int i=1;i<=n;i++)d[i]=inf;
    d[1]=0;
    memset(done,0,sizeof done);
    priority_queue<node> pq;
    pq.push(node(d[1],1));
    
    while(!pq.empty()){
        node nd=pq.top();pq.pop();
        int u=nd.i;
        if(done[u]||h[u]<low||h[u]>high)continue;
        done[u]=1;
        for(int v=1;v<=n;v++){
            if(h[v]<low||h[v]>high)continue;
            if(map[u][v]&&d[v]>d[u]+map[u][v]){
                d[v]=d[u]+map[u][v];
                pq.push(node(d[v],v));    
            }
        }
    }
    return d[n];
}
int myabs(int x){return x>0?x:-x;}
int main(){
    int cas;
    scanf("%d",&cas);
    while(cas--){
        memset(map,0,sizeof map);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&h[i]);
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&a,&b,&c);
            if(map[a][b]&&map[a][b]<c)continue;
            map[a][b]=map[b][a]=c;    
        }
        
        int k=0;
        int lmin=min(h[1],h[n]),lmax=max(h[1],h[n]);
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++){
				if(min(h[i],h[j])>lmin||max(h[i],h[j])<lmax)continue;
                at[k].l=min(h[i],h[j]);
                at[k++].h=max(h[i],h[j]);
            }    
        }
        sort(at,at+k);
        for(int i=0;i<k;i++){
            int d=dij(at[i].l,at[i].h);
            if(d!=inf){
                printf("%d %d\n",at[i].h-at[i].l,d);
                break;        
            }    
        }
    }
    return 0;    
}


HDU3389 Game

能从A取一部分到B,当B<A,并且(A+B)%2=1,(A+B)%3=0,其中A,B是堆的编号

博弈,搞不来啊。将堆数分成两部分,一部分到终态要奇数步,一部分要偶数步。对奇数步的做NIM

#include<cstdio>
using namespace std;
int cas,n,a;
//1,3,4是最终状态,%6为0,2,5为奇数步,对这些堆做NIM游戏
int main(){
	scanf("%d",&cas);
	for(int ca=1;ca<=cas;ca++){
		int rs=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&a);
			if(i%6==0||i%6==2||i%6==5)rs^=a;
		}	
		printf("Case %d: ",ca);
		printf(rs?"Alice\n":"Bob\n");
	}
	return 0;	
}


HDU1496 Equations

简单的哈希,但是要注意在a,b,c,d都是正或者都是负的情况要直接排除,否则会TLE

#include<cstdio>
#include<string.h>
using namespace std;
int hash[2000005];
int main(){
	int a,b,c,d;
	while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF){
		//注意排除
		if((a>0&&b>0&&c>0&&d>0)||(a<0&&b<0&&c<0&&d<0)){
			printf("0\n");
			continue;	
		}		
		memset(hash,0,sizeof hash);
		for(int i=-100;i<=100;i++){
			for(int j=-100;j<=100;j++){
				if(i&&j)hash[a*i*i+b*j*j+1000000]++;	
			}	
		}
		int rs=0;
		for(int i=-100;i<=100;i++){
			for(int j=-100;j<=100;j++){
				if(i&&j)rs+=hash[-c*i*i-d*j*j+1000000];	
			}	
		}
		printf("%d\n",rs);
	}
	
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值