1.Victor and Machine
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5417
解题思路:
官方题解:
因为数据范围很小,所以我们可以手动模拟,枚举每个小球弹出的时刻,再特判一下机器的关闭情况就可以了。实际处理起来的话或许有些蛋疼,但是,只要细心一点并且耐心一点,都是能够AC的。
另外一种解法就是推公式,我们发现,在机器每次开启的时间,都有x/w+1个小球被弹出(无论w是否整除x),假设这个数目为a,那么每弹出a个小球就需要花费x+y的时间,那么,第n个小球弹出的时刻就是(n-1)/a*(x+y)+(n-1)%a*w。要注意的是,这里需要用(n-1)%a*w,因为题中求的是第n个小球弹出的时刻等于是弹出n-1个小球所花费的时间,然而,只要测试一下样例就能注意到这一点了。
AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
int x,y,w,n;
while(~scanf("%d%d%d%d",&x,&y,&w,&n)){
int ans = 0,sum;
int i = 1;
while(i < n){
sum = 0;
while(i < n){
if(sum+w > x)
break;
sum += w;
ans += w;
i++;
}
if(i == n)
break;
ans += (x-sum)+y;
i++;
}
printf("%d\n",ans);
}
return 0;
}
2.Victor and World
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5418
解题思路:
http://blog.csdn.net/piaocoder/article/details/47952855
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f;
const int N = 18;
//输入
int n,m;
int dis[N][N];
int dp[1<<N][N];//记忆化搜索使用的数组
void floyd(){
for(int k=0; k<n; k++)
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
if(dis[i][k]+dis[k][j]<dis[i][j])
dis[i][j]=dis[i][k]+dis[k][j];
}
void solve(){
//用足够大的值初始化数组
memset(dp,INF,sizeof(dp));
dp[(1<<n)-1][0] = 0;
//根据递推式依次计算
for(int s = (1<<n)-2; s >= 0; s--){
for(int v = 0; v < n; v++){
for(int u = 0; u < n; u++){
if(!(s>>u & 1)){
dp[s][v] = min(dp[s][v],dp[s|1<<u][u]+dis[v][u]);
}
}
}
}
printf("%d\n",dp[0][0]);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
int u,v,w;
memset(dis,INF,sizeof(dis));
for(int i = 0; i < n; i++)
dis[i][i] = 0;
for(int i = 1; i <= m; i++){
scanf("%d%d%d",&u,&v,&w);
u--;v--;
dis[u][v] = dis[v][u] = min(dis[u][v],w);
}
floyd();
solve();
}
return 0;
}