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