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);
}
}