- 博客(42)
- 收藏
- 关注
转载 hdu 4939 Stupid Tower Defense
题目链接:hdu 4939 Stupid Tower Defense题目大意:塔防游戏,一个长度为n的路,给定x,y,z和t。然后对应每个长度的位置可以放攻击塔,有三种:红塔:怪在红塔所单位长度内每秒受到x点伤害。绿塔:怪经过绿塔之后,每秒受到y点伤害。蓝塔:怪经过后每走一格的时间加上z。求最大伤害。解题思路:更具塔的性质,红塔肯定放在最后,所以有dp[i][j]表示到
2014-08-23 11:46:32
1048
原创 Tyvj 1125
显然需要排序。对于第i个筷子,如果我们将它选入,那么必将和第i-1个筷子配对,这样平方差是最小的dp[i][j]表示前i个筷子,已经选择了j个筷子的最小的代价dp[i][j]=min(dp[i-1][j],dp[i-2][j-2]+sqr(a[i]-a[i-1]))初始化条件dp=maxint;dp[0][0]=0;注意j的枚举。#include#include
2014-08-23 11:44:09
451
原创 Uva 10714
/*Name: Copyright: Author: Date: 17/08/14 22:13Description: 注意到蚂蚁碰撞后跟碰撞前其实是相当于直接穿过去,对结果并没有产生影响,只是蚂蚁的编号有所变化,所以忽略碰撞即可。 */#include#includeusing namespace std;int main(){int casenu
2014-08-17 22:11:36
489
转载 Vijos P1741 观光公交
NOIP 2011 day2观光公交问题描述 风景迷人的小城 Y 市,拥有n 个美丽的景点。由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务。观光公交车在第0 分钟出现在1号景点,随后依次前往2、3、4……n 号景点。从第i 号景点开到第i+1 号景点需要Di 分钟。任意时刻,公交车只能往前开,或在景点处等待。
2014-03-08 23:30:09
1275
原创 Vijos 1471 教主的游乐场
首先仔细观察发现一些性质比如最多向左跳一次,而且必须第一次就跳。这样只要每次让跳到的新的i+a[i]尽量的大就可以了。(60分做法)把握住让i+a[i]尽量大,考虑将每一个装置的可以向后跳到的区间按照右端点从小到大排序(因为左边随便跳),倒序枚举,从问题的最后一步向前推,首先确定一个区间的右端点j,使得j在能用k步跳出的区间的最左端,若当前区间右端点>j,显然ans=k,同时我们要记录
2014-03-02 17:12:19
766
原创 Vijos P1763 Wormhole
贪心题目。显然可以发现一个性质。。。接下来就是二分判断。。首先二分一个最大路径,然后枚举虫洞的位置,考虑冲突时决策的调整。先将虫洞的位置设在第一个到1距离>mid的点,然后继续向后扫描,发现一个点j到i的距离也大于mid,这样就将j-1设成虫洞,然后看后面的点到j-1的距离是否符合要求。这样做一定是最优的。(因为要想满足全部条件,首先局部必须满足,否则就无法满足全部条件,因
2014-03-02 11:37:30
617
原创 Vijos P1615 旅行
很好的一道贪心题目。。。/*考虑相邻的三个数a,b,c(b>a>c)因为消耗的体力是差的绝对值,所以考虑要修改b,此时应该把b修改成a体力是b-a+c-a若修改成c的话体力是b-c+a-c由不等式可以得到,这个时候应该修改成较高的那一个,对于山谷,同理可得。*/#include#include using namespace std;int a[10
2014-02-20 15:50:25
596
原创 Vijos 1513 紧急救援
经典贪心先按h小到大排然后搞个极大堆把所有伤员的t一个一个加进堆中如果 堆总和+现在伤员的t否则如果 现在伤员的t最后堆元素数就是答案了#include#include #include using namespace std;struct ntype{ int h,t;};ntype a[50010]; p
2014-02-05 21:19:22
758
原创 Vijos 1144 小胖守皇宫
经典题不解释。。(貌似代码写的很挫)#include#include #include#define INTMAX 2000000000using namespace std;int f[2000][3],b[2000][2000],c[2000],inf[2000];int dp(int i,int j){ int ans=0; if(f[i
2014-02-05 21:10:05
1307
原创 洛谷 P1846 游戏
给定两个正整数数列,你要用它们来做一个游戏:你需要对数列进行若干次操作,每一次操作,应选择两个正整数K1和K2 ,并删除第一个数列的最后K1个数,计算出它们的和S1;删除第二个数列的最后K2个数,计算出它们的和S2。这一次操作的得分就是(S2-K2 )*(S1-K1 )。两个数列应同时被清空,不允许一个数列空了,而另一个数列中还有数。游戏的总得分就是每一次操作的得分总和。求最小的总得分。
2014-02-05 19:30:41
933
1
原创 Wikioi 1258 & Vijos 1150 关路灯
一道经典的DP。。。。。比较详细的DP题解抄下来了=。=分析:上次我是DFS+剪枝AC的,但是教材说这题的正解是DP,所以我就思考了一下DP的思路,现在说一下思路吧:老张每次只有两种决策,关掉当前最左边没有关掉的灯或关掉最右边没有关掉的灯,也就是说老张关灯的状态一定是一条直线(“直线”这个词这个可能不太好理解),我举个例子吧:比如当前的街道上有n盏路灯,用0表示当前路灯开着,1表示当前
2014-02-02 13:09:39
799
原创 Vijos 1061
题目中的按升序排列启示了我们DP的顺序,我们先考虑按升序DP,这时会发现决策的时候第i个必定是站在中间的,对答案不产生影响,故无法转移,这样就可以考虑倒着DP,从后往前进行DP。决策的时候需要注意,并不是一个一个的决策,而是两个两个的决策,即每次决策两个最矮的人,这样就容易转移。(所以转移的时候是f[i-2]而不是f[i-3],因为选了i和i-1在1~i-2中剩下的任何一个人都比他们高,不产生影响
2014-02-02 10:01:07
613
原创 Vijos 1059
背包问题,水过。。。。。#include#include#includebool dp[200][100000];int a[200][200]; int n,maxh=0;using namespace std;void work(int m){ for(int i=1;i<=a[m][0];i++) for(int j=maxh;j>=dp[m][i];j--)
2014-02-01 19:31:20
629
原创 Wikioi 1261 龙王的礼物
http://www.wikioi.com/problem/1261/继续搬运。。。用f[i][j]表示前j个数,取出来一些数,他们的和mod n为i时,这个和的最大值.num[i][j]表示这个最大值的情况下,取的最少的块数.a为原数组,则f[i][j]=max(f[i][j-1], f[ ((i-a[j])%n+n)%n ] + a[j])(分别表示不取此数与取此数),当括号内二者相同
2014-01-28 21:33:53
754
原创 Wikioi 2572 路面修整
http://www.wikioi.com/problem/2572/赶脚挺不错的一道DP。。。。抄过来。思路分析:显然(?)修整后的路面一定是原路面的某个值。创建新数组c等于原数组,然后将c排序,f[i][j]表示原数组前i个数变为单调上升,且i是c中的第j个数。f[i][j]=min(f[i-1][k]+abs(a[i]-c[j])); 但是还可以优化,用一个g[i
2014-01-28 21:26:45
906
原创 Vijos P1055 奶牛浴场
详见(《用极大化思想解决最大子矩阵问题》论文)(这算个毛。。。。)#include#includeusing namespace std;struct newtype {int x,y;};newtype a[6000];bool cmp(const newtype &p,const newtype &q) {return(p.x<q.x);}int main(){
2014-01-28 19:42:17
849
转载 Vijos P1006 晴天小猪历险记
背景 Background 在很久很久以前,有一个动物村庄,那里是猪的乐园(^_^),村民们勤劳、勇敢、善良、团结…… 不过有一天,最小的小小猪生病了,而这种病是极其罕见的,因此大家都没有储存这种药物。所以晴天小猪自告奋勇,要去采取这种药草。于是,晴天小猪的传奇故事便由此展开……描述 Description 这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知
2014-01-27 19:19:38
1560
原创 [Vijos1037]搭建双塔
两个背包来防止重复。。 #include#include bool dp[2000][2000];int h[2000]; int main(){ memset(dp,0,sizeof(dp)); int n,suma=0; dp[0][0]=true; scanf("%d",&n); for(int i=1;i<=
2014-01-25 20:00:33
762
原创 Vijos P1090连续数之和
维护前缀和假设有一段前缀和i~jsum[j]-sum[i-1] mod k=0显然sum[i-1] mod k=sum[j] mod k这样在读入的时候我们可以统计mod k余数为r的个数。在余数相同的数中,任意两个匹配都可以。ans+=n*(n-1)/2 n为余数为r的数的个数。注意特殊情况!#include#define MOD 1234567int f[1
2013-12-10 23:19:38
640
原创 1192: [HNOI2006]鬼谷子的钱袋
竟然没发现这道大水题。。。。好像背包九讲里写过。什么二进制拆包。。。这个好像更弱。。。。答案即为(int)(log2(m))+1证明?显然。。。。。代码:#include#includeint main(){ int m; scanf("%d",&m); printf("%d",(int)log2(m)+1); while(1);
2013-12-08 12:37:28
668
原创 1996: [Hnoi2010]chorus 合唱队
区间DP: f[i][j][0]表示目标队形中[i,j]这一段最左边(i)是刚放上去的数的方案数 f[i][j][1]表示目标队形中[i,j]这一段最右边(j)是刚放上去的数的方案数 转移是十分显然的。 注意一下初始化:f[i][i+1][0]=f[i][i+1][1]=1 (a[i]f[i][i+1][0]=f[i][i+1][1]=0 (a[i]>
2013-12-08 08:19:18
677
原创 2697: 特技飞行
贪心。其实只需要考虑每个活动执行两次。显然大的放首尾。#include#includeusing namespace std;int c[100000];int main(){ int n,k,ans=0; cin>>n>>k; for(int i=1;i<=k;i++) cin>>c[i]; sort(c+1,c+k+1);
2013-12-07 15:33:40
785
转载 1041: [HAOI2008]圆上的整点
数论题无力Orz...看了下题解,所以总结下吧,主要是运用gcd和分解质因数来进行优化。。觉得写得很好,所以把题解搬过来了=。=首先让我们一起来推下公式:x^2+y^2=r^2 y^2=r^2-x^2 y^2=(r-x)(r+x)到这里为止应该都很容易想到,接下来是关键设d=gcd(r-x,r+
2013-12-07 13:50:41
674
原创 2431: [HAOI2009]逆序对数列
考虑直接把答案作为状态进行DP(递推)f[i][j]表示1~i产生j个逆序对数的可能有多少种。对于第i个数,显然他比1~i之间的数都要大,所以容易得出状态转移方程:f[i][j]=sum(f[i-1][k])然后就好了。。上代码(好短)#includeusing namespace std;const int MOD=10000;int f[2000][2000];
2013-12-07 12:38:05
1182
原创 2748: [HAOI2012]音量调节
很朴素的DP。。竟然是省选题。。。。。。直接上代码:#includeusing namespace std;bool dp[100][10000];int c[1000];int main(){ int n,s,maxlevel; scanf("%d%d%d",&n,&s,&maxlevel); for(int i=1;i<=n;i++)
2013-12-07 07:36:36
1051
原创 1037: [ZJOI2008]生日聚会Party
o(╯□╰)o看了题解才会。。所以总结一下吧。。。这道题是dp或者说是递推。显然m,n要放到状态里,考虑直接用题目的答案来推答案。问题是要保证相差个数不超过k来进行转移,这里转移的时候是用前面的来推后面的。一开始想用f[i,j,k]表示i个男孩j个女孩男孩比女孩最多多k的方案数量,但是就无法记录女孩比男孩多的情况。设dp[i][j][x1][x2]表示i个男孩j个女孩男孩最
2013-12-01 16:20:31
903
原创 1978: [BeiJing2010]取数游戏 game
类似最长上升子序列的做法,只不过有个要求就是gcd必须要>l,这样根号n枚举因数,然后dpdp[i]表示以i作为最大公因数可以选的数的最多个数 满足gcd>l才更新dp#include#includeusing namespace std;int dp[2000000],a[100000];int main(){ int n,l,ans=0,k; scanf(
2013-12-01 15:34:03
943
原创 BZOJ 1831 中位数图
容易发现对于每一个数,我们只需要知道他是否大于中位数(b),所以对于每一个数特殊处理一下,大于中位数的填1,小于的填-1,这样问题就转化为了能选多少个子序列使得和为0。考虑到每一个数的范围都在1~n之间,所以使用哈希的思想。设pos表示中位数的位置 sum[i]表示1~pos和为i的子序列的个数首先预处理出来1~pos之间的sum,然后枚举右端点:假设从pos到目前位
2013-11-29 23:38:16
873
原创 BZOJ 1786 配对Pair
注意到-1的位置所填的数一定是不下降的,而且k的值非常的小,所以考虑DP。设dp[i][j]表示在前i个-1的位置上,第i个-1的位置上填数字j所产生的最少逆序对数目,那么求出来之后只需要加上开始时的逆序对数即可。需要预处理出来两个数组,big[i][j]和small[i][j]分别表示,在第i个数前面并且比数字j大的数字的个数,在第i个数后面并且比j小的数字的个数,这样的话dp[i]
2013-11-26 22:32:02
971
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人