泰山挑夫【三】解题报告
来源:互联网 发布:龙城飞将 知乎 编辑:程序博客网 时间:2024/05/17 05:05
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=29405#problem/A
这场比赛可能题目有点难,只出了一个水题,郁闷啊! 另外还可以做的题有这么几个!
H题,告诉你多组比赛,还有胜败情况,看有多少人能够确定最终名次! 当时想到拓扑排序,但是无论正着拍,逆向拍都不对,我后来又改成迭代,但是仍然不对,郁闷啊!
自己想了测试数据,想了好几个都没测出问题了,后来还是老卜告诉我一组数据,但是没有对题目理解透彻,即便知道了测试数据仍然没有做对! 后来想想也是,怎么才能把一个人的最终名次确定了呢, 那就是在总人数为n的前提下,赢他的有m人,输他的有k人,m+k=n-1那么他的名词就一定能确定了呢! 当然,很多关系是能传递的,1》2,2》3 那么1》3 赢不一定是直接赢,简介赢也行,那么就需要用floyd处理一下…… 然后记录入度和出度就好,每找出一个人就把这个人从总人数中去掉,然后把他在人数中的关系也都去掉,这样再次迭代下去,直到没有不能更新答案为止……
G 这是到DP,很明显的DP,而且是纯粹的DP,枉我搞DP快一暑假了,仍然一点头绪没有,后来才知道自己陷入误区了
先介绍下题意吧,n个时间1W,然后给每个时间能跑的距离,没跑动一次疲劳就上升一个值,最多到M,如果休息的话,每停一次疲劳下降1,但是疲劳下降的时候不能终止,必须降到0才能开始下一次运动…… 疲劳从0开始,但是最后在n时刻,疲劳必须要降到0,否则很难做下一次训练,休息不好时不行的!
当时各种想法都出来了,就是没有一个靠谱的,要不就是不知道该记录那个状态,要不就是没法记录状态,再就是没法转移,对状态把握不清楚,当时想用dp[i][0/1]的形式,就是每个点选还是不选的形式,但是后来怎么弄都不对,因为还有个疲劳值不超过m限制在这里…… 而且dp里面记录跑的最远的距离或者最小疲劳值都不对啊…… 知道看到别人的讲解才恍然大悟。我可以这样开dp[n][m] 的形式啊,最终需要的结果就是时间为n,疲劳为0的状态
当然这里转移的时候需要注意,dp[i][0]可能有上一个的1疲劳转移过来,也可能由前两个的2疲劳转移过来,或者前k个k疲劳转移过来…… 这样就很清楚了,因为他要连续休息知道j个疲劳回复到0啊!
F题是个图论题,就是给一些边,然后建图,类似于求最短路一样,把节点1和节点n连接起来,然是有k条边是不用自己花钱的,剩下的边由jhon自己掏钱,花费是,最长的一条的长度! 当时没读明白题,到现在其实也不是很明白,我以为k是长度,而不是边的数目!
这样题意明确之后就应该知道,尽量在求解修路的时候使得长的边算到k里面,剩下的自己搞;可是把那些边算到k里面不花钱,那些需要算到Jhon的头上,确实不好搞啊,怎么办呢? 难道枚举,爆搜,贪心,orDP ,而且不知道怎么判断是否是用那些边不用那些边; 后来看了别人的讲解有点明白了,二分啊,二分长度,看至少有k条边大于L,然后用这些边修路看能否修好,怎么算是修好了,而且恰好用了那几条选中的边呢? 修改权值,超过L的设成1,其他的弄成0; 若如果修好的最短路答案恰恰是k,那么正好全用了…… 这样来验证…… 通过修改权值的办法;这样在最短路里面把无关的边设成0消除其影响!
当然,貌似也有用DP+搜所做出来的,貌似思路是枚举这条边看能否归0,就是让通讯公司掏钱而不是让可怜Jhon掏钱,然后DP记录最优值,减少枚举搜索次数http://hi.baidu.com/lxxstar1226/item/d036b2e45b534a334cdcaf65
B题是大水题。披着计算几何的外衣,而且里面的词汇全是计算几何里面碰到的词汇。要不是哥刚做过几个计算几何,连题目大意都读不懂啊,给你一个矩形,然后看最小的等腰三角形把矩形套起来,使矩形上的点要么在内部要么在边上上,而且等腰三角形的两边已经确定了,和XX重合,花花图,三角形相似,直接利用题目中所给的值就好,都不用计算的,只不过坐标得处理下,分类讨论加上正负号就好了……
G题:
G题:
#include <iostream>#include<cstdio>using namespace std;#define N 100000#define M 500int dp[N+10][M+10];int cnt[N+10][2];int d[N+10];int sum[N+10];int n,m;int main(){///该死的DP,做了这么久的DP还是别难住了,悲剧啊,都不好意思说自己是搞DP的,///做DP貌似有点盲目了,丢掉了思考,最近做多了dp[i][0/1] 这一位放还是不放的形式忽略了一般的二维数组形式的DP///忘记了最终状态是需要时间是n,但是疲劳值是0的最终状态,因为每个状态需要积累疲劳值啊,当时光盲目的开两个数组///却忽略最基本的二维数组的形式啊,哎,忽略了二维数组的形式导致好多状态没法记录啊 cin>>n>>m; for(int i=1; i<=n; ++i) { scanf("%d",&d[i]); sum[i]=sum[i-1]+d[i]; } dp[1][0]=0; dp[1][1]=d[1]; for(int i=1;i<=m;++i) { dp[1][i]=d[1]; } for(int i=2;i<=n;++i) { dp[i][0]=max(dp[i-1][0],dp[i][0]); for(int j=1;j<=m;++j) { dp[i][j]=max(dp[i-1][j-1]+d[i],dp[i][j]); ///下面这句有点难理解,为什么呢,就是说如果i时消耗为0的话,那么消耗为为j的就得从i-j开始转移, ///因为这段必须是是连续的休息时间 if(i>j)dp[i][0]=max(dp[i-j][j],dp[i][0]); } } cout<<dp[n][0]<<endl; return 0;}
H题:
#include <iostream>#include<cstring>#include<stack>#include<algorithm>using namespace std;int n,m;int cnt2[110];///表示出度int cnt1[110];///表示入度int vis[110];int map[110][110];int u,v,ans;int a1=0,a2=0;void floyd(){///floyd一边是关系传递…… for(int k=1; k<=n; ++k) { for(int i=1; i<=n; ++i) { for(int j=1; j<=n; ++j) { if(map[i][k]&&map[k][j])map[i][j]=1; } } }}void slove(){ int t=n; int tmp=-1; while(tmp!=t) {///迭代的过程,直到不能找到为止 tmp=t; for(int i=1;i<=n;++i) { if(!vis[i]&&cnt1[i]+cnt2[i]==t-1) {///如何赢的人输的人还有他自己是总人数的话,那么一定能确定他的名词了 ans++;vis[i]=1; t--; for(int j=1;j<=n;++j) { if(map[j][i])cnt2[j]--; if(map[i][j])cnt1[j]--; } } } }}void init(){ memset(map,0,sizeof(map)); memset(cnt1,0,sizeof(cnt1)); memset(cnt2,0,sizeof(cnt2)); memset(vis,0,sizeof(vis)); ans=0;}int main(){///如何根据一个人的比赛情况确定排名呢,那就是根据他赢的人数还有输的人数!!! 就是入度和出度///当年usaco月赛上曾经有一个题是将带编号打乱编号在重新排列,告诉你每个牛左边有多少个比他编号小的,然后输出///每个牛的编号,怎么办呢? 倒着推啊,比如说全班有多少个人比他成绩高,那么他是倒数第几不就很好确定了吗///可惜当时没想明白,而且怎么找数据就是没有找出来,后来老卜给了我一组 1,2都打败3,3打败4,5///那么3号的名词一定是确定了, 我原来是正向一边拓扑排序,逆向一边拓扑排序;光想着从两头找了,没有想到中间也是有可能的 cin>>n>>m; for(int i=0; i<m; ++i) { cin>>u>>v; map[u][v]=1; } floyd();///传递 ///统计入度出度 for(int i=1; i<=n; ++i) { for(int j=1; j<=n; ++j) if(map[i][j]&&i!=j)cnt1[j]++,cnt2[i]++;; } slove(); cout << ans << endl; return 0;}
- 泰山挑夫【三】解题报告
- 泰山挑夫解题报告
- 泰山挑夫2 解题报告 我能说脏话嘛!又被字符串读入给坑了
- 泰山挑夫1
- 泰山挑夫1
- 泰山挑夫2
- 暑期训练-泰山挑夫1
- 暑期训练-泰山挑夫2
- 一二三解题报告
- 泰山
- 2011新生练习赛三解题报告
- leetCode解题报告5道题(三)
- 三重镇——解题报告
- 赛码解题报告(三)
- 【解题报告】Vijos1143 三取方格数
- 【解题报告】Vijos1143 三取方格数
- 【解题报告】Vijos1143 三取方格数
- 【解题报告】Vijos1143 三取方格数
- djanglebook
- Pieces(hdu4628,状态压缩的动态规划)
- Android-GPS定位
- SRM 588 D2 L2:GUMIAndSongsDiv2,冷静思考,好的算法简洁明了
- 不使用额外空间实现两个变量(int 型)的交换
- 泰山挑夫【三】解题报告
- 循环右移字符串简易探讨
- Sad Love Story(hdu4631,模拟+set容器)
- 创建一个和已知表相同的表
- 大数据相乘
- 求数组中和最大的子数组与始末下标
- 理解WebKit和Chromium:Chromium资源磁盘缓存
- Balls Rearrangement(hdu4611,模拟+数学)
- 将数组中指定的前N位移动到数组的最后面