[ACM] HDU 1006 解题报告
偶尔写写ACM水题还是挺好玩的。(好吧其实是老婆求助我才看滴)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1006
一开始看到这题的时候,感觉一天24小时60分钟60秒。把每一秒的最小指针角度记下来再搞个排序。
偶尔写写ACM水题还是挺好玩的。(好吧其实是老婆求助我才看滴)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1006
一开始看到这题的时候,感觉一天24小时60分钟60秒。把每一秒的最小指针角度记下来再搞个排序。
今天心情好,刷了两到ACM水题,思路很简单都在注释里,所以直接贴代码:
/**
* @file 龟兔赛跑.cpp
* @brief 龟兔赛跑 AC代码 (DP)
* DP方程式: [到第i的充电站的最短时间] = [到最后一个冲了电的充电站的最短时间] + [那个充电站到第i个充电站的时间]
*
* @link http://acm.hdu.edu.cn/showproblem.php?pid=2059
* @version 1.0
* @author OWenT
* @date 2013.07.15
*
* @history
*
*
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <numeric>
int pn[128];
double dp[128]; /** dp[i] 表示 到第i个充电站的最小时间(0为开始位置,n+1为终点) **/
double calc_charge_time(int dis, int v1, int v2, int c) {
if (dis <= c)
return 1.0 * dis / v1;
return 1.0 * c / v1 + 1.0 * (dis - c) / v2;
}
int main(int argc, char* argv[]) {
using namespace std;
double eps = std::numeric_limits<double>::epsilon();
int l, n, c, t, vr, v1, v2;
while(cin>> l) {
cin >> n>> c>> t>> vr>> v1>> v2;
pn[0] = 0; /** 0为起点 **/
for (int i = 1; i <= n; ++ i) {
cin>> pn[i];
}
pn[n + 1] = l; /** n+1为终点 **/
memset(dp, 0, sizeof(dp));
for(int i = 0; i <= n + 1; ++ i) {
dp[i] = calc_charge_time(pn[i] - pn[0], v1, v2, c);
}
for(int i = 1; i <= n + 1; ++ i) {
for(int j = 0; j < i; ++ j) {
double tc = calc_charge_time(pn[i] - pn[j], v1, v2, c) + t + dp[j];
dp[i] = std::min(tc, dp[i]);
}
}
double rt = 1.0 * l / vr, tt = dp[n + 1];
if (tt < rt)
puts("What a pity rabbit!");
else
puts("Good job,rabbit!");
}
return 0;
}
/**
* @file Zipper.cpp
* @brief Zipper AC代码 (DP)
* @link http://poj.org/problem?id=2192
* DP方程式: [A串消耗个数i][B串消耗个数j] = min{[A串消耗个数i - 1][B串消耗个数j]|[A串消耗个数i][B串消耗个数j + 1]}
* 以上分支选取条件是 A或B的新选用字符和C串新字符匹配
*
* @version 1.0
* @author OWenT
* @date 2013.07.15
*
* @history
*
*
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <numeric>
char strA[256], strB[256], strC[512];
int dp[256][256]; /** dp[i][j] = k 表示A消耗了i个字符,B消耗了j个字符,拼成的C串消耗了k个字符(其实就是i+j) **/
int main(int argc, char* argv[]) {
using namespace std;
int s, n;
scanf("%d", &n);
for( s = 0; s < n; ++ s) {
scanf("%s %s %s", strA, strB, strC);
int lenA = strlen(strA);
int lenB = strlen(strB);
int lenC = strlen(strC);
bool bFlag = false;
if ( lenC != lenA + lenB ) {
printf("Data set %d: no\n", s + 1);
continue;
}
memset(dp, 0, sizeof(dp));
if (strA[0] == strC[0])
dp[1][0] = 1;
if (strB[0] == strC[0])
dp[0][1] = 1;
for (int i = 0; i <= lenA; ++ i) {
for (int j = 0; j <= lenB; ++ j) {
if (0 == dp[i][j])
continue;
int ri = i + 1, rj = j + 1;
if (strA[i] == strC[dp[i][j]]) {
dp[ri][j] = dp[i][j] + 1;
if (ri + j == lenC)
bFlag = true;
}
if (strB[j] == strC[dp[i][j]]) {
dp[i][rj] = dp[i][j] + 1;
if (i + rj == lenC)
bFlag = true;
}
}
}
printf("Data set %d: %s\n", s + 1, bFlag? "yes": "no");
}
return 0;
}
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3398
题目要我们计算1,0的排列方式总数,并且对任意长的字符串,1的数量大于等于0的数量
我们可以把题目转化为从(0,0)点到(m,n)点的方法总数,且路径不经过y=x-1这条直线
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3400
这题就是一道简单的两重三分
首先设e点为从ab上离开的点,f为从cd上进入的点
显然对固定点e,f从距c的距离的长度是一个单调函数或者先减后增的函数,这里可以三分算出最优解。这里是第一个三分
题目: http://acm.hdu.edu.cn/showproblem.php?pid=3336
水题一道,主要是测试数据很水
不解释,贴代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
char str[200005];
vector<long>glo_Pos;
int main()
{
int t;
long output,i,n,j;
scanf("%d",&t);
while(t --)
{
output = 0;
glo_Pos.clear();
scanf("%ld %s", &n, str);
for(i = 0; i < n; i ++)
{
if(str[i] == str[0])
{
glo_Pos.push_back(i);
output ++;
}
}
output = output % 10007;
for(i = 1; i < n; i ++)
{
for(j = 0; j < glo_Pos.size();j ++)
{
if(str[i] == str[glo_Pos[j] + i])
output = (output + 1) % 10007;
else
{
glo_Pos.erase(glo_Pos.begin() + j);
j --;
}
}
}
printf("%ld\n", output);
}
return 0;
}