这次比赛题有点难。。我在谷大哥的帮助下把第一题A了。。斌哥在自己的努力下把第二题A了。。于是我们拿到了。。Rank 58 。。。。。。有点夸张啊。。。我最后看了看。。一共才180个人A出来题了。。。难道其他120个名额要分给那些疯狂刷wa的人??不叨叨了看题。。。
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4525
题解:
#include
#include
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 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
#include
#include
#include
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
#include
#include
#include
#include
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 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
#include
#include
#include
#include
#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 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
#include
#include
#include
#include
#include