这次比赛题有点难。。我在谷大哥的帮助下把第一题A了。。斌哥在自己的努力下把第二题A了。。于是我们拿到了。。Rank 58 。。。。。。有点夸张啊。。。我最后看了看。。一共才180个人A出来题了。。。难道其他120个名额要分给那些疯狂刷wa的人??不叨叨了看题。。。
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4525
题解:
#include <iostream> #include <cmath> using namespace std; int main() { int T, Case = 0; scanf("%d", &T); while (T--) { Case++; int n, k1, k2; __int64 k; __int64 sum = 0, sum1 = 0; scanf("%d %d %d %I64d", &n, &k1, &k2, &k); int i; __int64 tmp; for (i=0; i<n; i++) { scanf("%I64d", &tmp); sum += tmp; } printf("Case #%d: ", Case); sum1 = sum; for(i=0;;i++) { if(sum1 > k) { printf("%d\n",i); break; } sum = sum1; sum1 = sum*(k1+k2); if((sum >0 &&(k1+k2)>0 && sum1 <0)) { printf("%d\n",i+1); break; } if((sum <0 &&(k1+k2)<0 && sum1 <0)) { printf("%d\n",i+1); break; } if(i>100000) { printf("inf\n"); break; } } } return 0; }
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4526
题解:一下是斌哥AC代码
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 110; int dp[maxn][maxn]; int n, k, d, s; int cas; int t[maxn], z[maxn]; int main(void) { // freopen("f:\\code\\file\\data.txt", "r", stdin); scanf("%d", &cas); while(cas --) { scanf("%d%d%d%d", &n, &k, &d, &s); t[0] = 0; for(int i = 1; i <= k; i ++) scanf("%d%d", &t[i], &z[i]); for(int i = 0; i < maxn; i ++) dp[i][0] = 0; for(int i = 0; i < maxn; i ++) { for(int j = 1; j < maxn; j ++) { dp[i][j] = inf; } } for(int i = 1; i <= k; i ++) { for(int j = 1; j <= n; j ++) { dp[i][j] = dp[i - 1][j]; for(int k = 1; k <= z[i]; k ++)if(j - k >= 0) { dp[i][j] = min(dp[i - 1][j - k] + k * t[i] + d, dp[i][j]); } } } if(dp[k][n] == inf) printf("impossible\n"); else printf("%d\n", dp[k][n]); } return 0; }
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4527
题解:(转自大牛:http://blog.csdn.net/dyx404514/article/details/8720661)
思路:模拟题,要注意两个水珠同时到达一个4级水珠的情况,我用广搜过的,反正就是根据题意模拟,没什么好说的。代码如下:
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <queue> using namespace std; int bo[7][7]; int dir[4][2]={1,0,0,1,-1,0,0,-1}; int vis[7][7]; int check(int x,int y) { if(x<1||y<1||x>6||y>6) return 0; return 1; } void solve(int x,int y) { queue<int> q; bo[x][y]++; if(bo[x][y]>4) { vis[x][y]=0; q.push(x); q.push(y); q.push(0);//时间 q.push(-1);//方向 } int i; while(!q.empty()) { int xx=q.front();q.pop(); int yy=q.front();q.pop(); int tt=q.front();q.pop(); int d=q.front();q.pop(); if(d==-1) bo[xx][yy]=0; for(i=0;i<4;i++) { if(d!=-1&&d!=i) continue; int x1=xx+dir[i][0],y1=yy+dir[i][1]; if(check(x1,y1)) { if(bo[x1][y1]==0) { q.push(x1);q.push(y1);q.push(tt+1);q.push(i); } else if(bo[x1][y1]<4) { bo[x1][y1]++; } else if(bo[x1][y1]==4) { bo[x1][y1]++; vis[x1][y1]=tt+1; q.push(x1);q.push(y1);q.push(tt+1);q.push(-1); } else { if(tt+1<=vis[x1][y1]) bo[x1][y1]++; else { q.push(x1);q.push(y1);q.push(tt+1);q.push(i); } } } } } } int main() { //freopen("dd.txt","r",stdin); while(scanf("%d",&bo[1][1])!=EOF) { int i,j,n,x,y; for(i=1;i<=6;i++) { for(j=1;j<=6;j++) { if(i==1&&j==1) continue; scanf("%d",&bo[i][j]); } } scanf("%d",&n); while(n--) { scanf("%d%d",&x,&y); memset(vis,-1,sizeof(vis)); solve(x,y); } for(i=1;i<=6;i++) { for(j=1;j<=6;j++) { if(j!=6) printf("%d ",bo[i][j]); else printf("%d",bo[i][j]); } printf("\n"); } printf("\n"); } return 0; }
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4528
题解:(转自大牛:http://blog.csdn.net/dyx404514/article/details/8720661)
:搜索题,明显的宽度搜索,设dist[x][y][0]表示当前没看到大明和二明到达(x,y)时的最早时间,dp[x][y][1]表示看到大明没看到二明的最早时间,dp[x][y][2]表示看到二明而没看到大明的最早时间。我们首先预处理一下能看到大明和能看到二明的位置,然后就搜就是了。这里要注意的是我们不能穿过一个人,也就是我们要把大明和二明当做障碍物,具体看样例3。代码如下:
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <queue> #define maxn 110 #define inf 2100000000 using namespace std; int dir[4][2]={1,0,0,1,-1,0,0,-1}; int n,m; char bo[maxn][maxn]; int check(int x,int y) { if(x<1||y<1||x>n||y>m||bo[x][y]!='.') return 0; return 1; } int see[2][maxn][maxn]; int dist[maxn][maxn][3]; void init(int x,int y,int t) { int i; for(i=0;i<4;i++) { int xx=x+dir[i][0],yy=y+dir[i][1]; while(check(xx,yy)) { see[t][xx][yy]=1; xx+=dir[i][0]; yy+=dir[i][1]; } } } int bfs(int x,int y) { queue<int> q; dist[x][y][0]=0; int t,i; if(see[0][x][y]&&see[1][x][y]) return 0; q.push(x); q.push(y); q.push(0); while(!q.empty()) { int xx=q.front();q.pop(); int yy=q.front();q.pop(); int tt=q.front();q.pop(); int len=dist[xx][yy][tt]; //printf("%d %d\n",xx,yy); if(see[0][xx][yy]) { if(tt==2) return len; tt=1; } if(see[1][xx][yy]) { if(tt==1) return len; tt=2; } for(i=0;i<4;i++) { int x1=xx+dir[i][0],y1=yy+dir[i][1]; if(check(x1,y1)&&dist[x1][y1][tt]==-1) { dist[x1][y1][tt]=len+1; q.push(x1); q.push(y1); q.push(tt); } } } return inf; } int main() { //freopen("dd.txt","r",stdin); int ncase,time=0; scanf("%d",&ncase); while(ncase--) { printf("Case %d:\n",++time); int t,i,j; scanf("%d%d%d",&n,&m,&t); for(i=1;i<=n;i++) scanf("%s",bo[i]+1); int sx,sy,x1,x2,y1,y2; memset(see,0,sizeof(see)); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(bo[i][j]=='D') x1=i,y1=j; if(bo[i][j]=='E') x2=i,y2=j; if(bo[i][j]=='S') { bo[i][j]='.'; sx=i,sy=j; } } } memset(dist,-1,sizeof(dist)); init(x1,y1,0); init(x2,y2,1); //printf("f"); int ans=bfs(sx,sy); if(ans>t) printf("-1\n"); else printf("%d\n",ans); } return 0; }
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4529
题解:(转自大牛:http://hi.baidu.com/chenwenwen0210/item/6bcc70fc605fa4e4a835a28c)
解题报告:
一看这数据范围就想到了状态压缩DP,由于马的攻击范围最多是上下2行。
所以我们只要管好前面两行的就行了,
dp[i][j][p][q]
表示第i行放马的状态是q,第i-1行的状态是p,前i行放马的个数是j个的种数。
推i+1行的时候枚举第i+1行放马的状态,进行转移。
总的复杂度无法估计,理论上是(1<<8)*(1<<8)*(1<<8)*n*8
这里需要一些剪枝,不然是通不过的。加了很多的非法判断。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> #include<map> #include<string> #include<queue> #include<stack> #include<vector> #include<set> #include<list> using namespace std; typedef __int64 lld; const int MAX=10; const int INF=1000000000; const double EPS=1.0e-8; const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; int dblcmp(double x) { if(fabs(x)<EPS)return 0; return x<0?-1:1; } int a[MAX]; lld dp[2][11][1<<8][1<<8]; char s[MAX]; bool ok1[1<<8][1<<8]; bool ok2[1<<8][1<<8]; bool judge(int a,int b,int d) { int i; int x,y; for(i=0;i+d-1<8;i++) { x=1<<i; y=1<<i<<d; if((x&a)&&(y&b))return false; if((x&b)&&(y&a))return false; } return true; } int cnt[1<<8]; int count(int n) { int ret=0; while(n) { ret+=n&1; n>>=1; } return ret; } int main(){ int n=6; int i,j; int k; int T; int CS=1; for(i=0;i<(1<<8);i++) { for(j=0;j<(1<<8);j++) { ok1[i][j]=judge(i,j,1); ok2[i][j]=judge(i,j,2); } } for(i=0;i<(1<<8);i++) { cnt[i]=count(i); // printf("cnt[%d]=%d\n",i,cnt[i]); } //printf("%d\n",1<<8); scanf("%d",&T); while(T--) { scanf("%d",&n); for(i=0;i<8;i++) { scanf("%s",s); a[i]=0; for(j=0;j<8;j++) { a[i]*=2; if(s[j]=='*')a[i]++; } // printf("a[%d]=%d\n",i,a[i]); } memset(dp,0,sizeof(dp)); int xx=0; for(i=0;i<(1<<8);i++) { if(i&a[0])continue; if(cnt[i]>n)continue; dp[0][cnt[i]][0][i]++; xx++; //printf("i=%d\n",i); } // printf("xx=%d\n",xx); int tag=0; for(i=1;i<8;i++) { tag=i&1; for(xx=0;xx<=n;xx++) { for(j=0;j<(1<<8);j++) { for(k=0;k<(1<<8);k++) { dp[tag][xx][j][k]=0; } } } for(j=0;j<(1<<8);j++) { if(i-2>=0&&(j&a[i-2]))continue; for(k=0;k<(1<<8);k++) { if(k&a[i-1])continue; if(cnt[j]+cnt[k]>n)continue; if(!ok2[j][k])continue; int tt; for(tt=cnt[j]+cnt[k];tt<=n;tt++) { if(dp[1-tag][tt][j][k]==0)continue; for(int z=0;z<(1<<8);z++) { if(cnt[z]+tt>n)continue; if(z&a[i])continue; if(!ok2[z][k]||!ok1[z][j])continue; dp[tag][tt+cnt[z]][k][z]+=dp[1-tag][tt][j][k]; } } } } } lld ans=0; for(i=0;i<(1<<8);i++) { for(j=0;j<(1<<8);j++) { //if(dp[tag][n][i][j]>0)printf("%d %d\n",i,j); ans+=dp[tag][n][i][j]; } } printf("%I64d\n",ans); } return 0; } /* 2 1 *....... ....*... .......* .....*.. ..*..... ......*. .*...... ...*.... 2 1 ........ ........ ........ ........ ........ ........ ........ ........ 2 1 *******. ******** ******** ******** ******** ******** ******** ******** */