ZOJ 3352-3361||Monthly July 2010
2015-07-20 00:11
337 查看
按照难度从简单到难。不过榜歪了,准确来说是按照过题人数从多到少。
D题:题意是有三种赔率,现在问你有没有方案使得无论哪种结果出现都可以赚钱?
一开始的思路特别蠢,但是我忘记是啥了,等我明天去翻翻草稿纸再回来写。
翻到了。TAT 就是穷举方案,然后算出每个钱数用了多少,直接找规律,找了半天都没算出钱数要用多少……
其实设三个未知数列出不等式,就能知道。只要1/a+ 1/b+ 1/c 小于1就一定可以赚钱了,直接这样写会wa,记得要加上浮点误差的判断。或者是因为只有两位小数,直接把浮点数乘以一百然后加上一个EPS转换成整数就可以了。
H题:模拟题。我的姿势被批评很扭曲,但是一炮过,我很开心~~~~
E题:给你一些钱,让你怎么分三种赔率得到的钱最多。本来是三千毫秒,然后想着10的八次方暴力,然后循环里面大概有五十多步,TAT,WA了。
然后我仔细研究了样例。发现a的个数是(bc)* n/(ab+bc + ac)酱紫的,然后就做了,然而wa了,正确的做法应该是算出这个i之后往前延伸两个往后延伸两个,也就是i-2遍历到i+2.那么为什么要枚举呢?首先要先知道,为什么a的个数是(bc)* n/(ab+bc + ac)酱紫呢??晚上再写
A题:题意是有一个有向图,有“一面!!!”白旗和“一面!”黑旗。每人可以移动旗子,不能移动算输。问你先手想要收益最大,第一步有几种方案。
想起那个异或为0的也是问第一步有几种方案,当时推了一整场比赛。还有那个sg函数真的要好好看看了!!!!!然而和这一道题没啥关系。
这题就是用三维dp[i][j][k],i表示当前白旗位置,j表示当前黑旗位置,k表示我往下搜索之前场上的钱数,dp值存的是搜索结束后最大的收益。
对白旗跑一遍dfs,对黑旗跑一遍dfs。
至于方案数的判断,我原来用的做法是在main里面判断几种方案然后算,然而这样的话相当于转换了先手作为后手,会wa。要直接用记忆化搜索检查第一个人,同时加一个判断是否是第一步。
dp如果更新过就不用更新。
注意会出现负数。然后我开了大概8*(10^6)的数组。然后所有dp下标加上一个更正值就好啦。
神奇的事情是调用了dp[i][j][-1]居然不会报错。而是=0,简直神奇。
G题:有个妹子每天住在一个地方,她可以获得一定的收益,每一天得到的钱不同,然后她可以搬到指定的地方numi,那个地方的人类可以帮她搬,但是这个人类搬到某个指定的地方,妹子就要请这个人吃饭,花费指定的钱数bgmi,问妹子在d天晚上之前可以得到的最大钱数。
题解:dp[i][j][k] .i代表这是第i天下午,j代表今晚准备住在j号房子,k代表今晚住完了之后,累计在j住了k天。注意,一定能够要清楚dp中每一维代表的是今晚的情况还是昨晚的情况,很容易纠结不清。
然后这题有个巨大的问题。就是妹子一个下午可以搬家很多很多次啊!天啊,要跑一遍弗洛伊德得出每两个点的最小花费啊!注意正常的弗洛伊德,自己到自己的花费是0,但这道题自己到自己的花费要初始化成INF哟!然后和其他点等同,假如跑了一圈回到自己,那么今晚就相当于第1天而不是第k+1天。
弗洛伊德模板!注意不同问题有不同的初始化方法!!!
这道题的ac代码:
J题:模拟题。
注意的地方:“namely shifting amnesty for yellow cards from the end of the first round until after the quarter-finals
instead”
首先 四分之一决赛指的是倒数第三场……好吧……决赛<——半决赛<——四分之一决赛……
然后,这句话的 意思是指进入第五场时,前三场的黄牌就可以自动消失,第四场的黄牌保留。
还有,题目中也没说给的比赛号码是按顺序的。
以上。但我根本没做这道题,反正我模拟题的姿势渣的一比。
B题:有四种反转方案,只要你选择一种能经过最少次这种翻转可以得到全白的界面,如果有多种选择序号最小。
题解:首先弄一个可爱的矩阵,三行的。枚举每个方块出现的位置,也就是k从0到1<<15。只要k中哪个位置有1,就代表这个位置转一次。然后,注意有很多都是右侧一列最中间只有一个1的,把他们集体逆时针90度,然后只需要遍历第一行就知道放还是不放啦。
存矩阵的时候把每个角度都转一遍存下来~一共存四个矩阵,然后每个矩阵一行的十五个数字压缩成二进制表示一个数字。然后每种方法放的时候遍历第一行就好啦。
存方法数矩阵的时候有一个特别厉害的姿势可以存下k从0到1<<15中所有的矩阵。
所有的都逆时针九十度了所以记得原矩阵也要逆时针90度。
D题:题意是有三种赔率,现在问你有没有方案使得无论哪种结果出现都可以赚钱?
一开始的思路特别蠢,但是我忘记是啥了,等我明天去翻翻草稿纸再回来写。
翻到了。TAT 就是穷举方案,然后算出每个钱数用了多少,直接找规律,找了半天都没算出钱数要用多少……
其实设三个未知数列出不等式,就能知道。只要1/a+ 1/b+ 1/c 小于1就一定可以赚钱了,直接这样写会wa,记得要加上浮点误差的判断。或者是因为只有两位小数,直接把浮点数乘以一百然后加上一个EPS转换成整数就可以了。
H题:模拟题。我的姿势被批评很扭曲,但是一炮过,我很开心~~~~
E题:给你一些钱,让你怎么分三种赔率得到的钱最多。本来是三千毫秒,然后想着10的八次方暴力,然后循环里面大概有五十多步,TAT,WA了。
然后我仔细研究了样例。发现a的个数是(bc)* n/(ab+bc + ac)酱紫的,然后就做了,然而wa了,正确的做法应该是算出这个i之后往前延伸两个往后延伸两个,也就是i-2遍历到i+2.那么为什么要枚举呢?首先要先知道,为什么a的个数是(bc)* n/(ab+bc + ac)酱紫呢??晚上再写
A题:题意是有一个有向图,有“一面!!!”白旗和“一面!”黑旗。每人可以移动旗子,不能移动算输。问你先手想要收益最大,第一步有几种方案。
想起那个异或为0的也是问第一步有几种方案,当时推了一整场比赛。还有那个sg函数真的要好好看看了!!!!!然而和这一道题没啥关系。
这题就是用三维dp[i][j][k],i表示当前白旗位置,j表示当前黑旗位置,k表示我往下搜索之前场上的钱数,dp值存的是搜索结束后最大的收益。
对白旗跑一遍dfs,对黑旗跑一遍dfs。
至于方案数的判断,我原来用的做法是在main里面判断几种方案然后算,然而这样的话相当于转换了先手作为后手,会wa。要直接用记忆化搜索检查第一个人,同时加一个判断是否是第一步。
dp如果更新过就不用更新。
注意会出现负数。然后我开了大概8*(10^6)的数组。然后所有dp下标加上一个更正值就好啦。
神奇的事情是调用了dp[i][j][-1]居然不会报错。而是=0,简直神奇。
/* dp[i][j][k]表示白棋在i,黑棋在j,然后现在局面上可以获得的是k 转移的就是前面的相反数的最大值(表示我走完这一步可以得到的钱数)上一步是对手走的我不管 TAT最后的结果就是终态,遍历i可走的地方,j可以走的地方 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define SIZE_D 55 #define SIZE_B 2605 #define INF 0x3f3f3f3f using namespace std; int digit[SIZE_D]; //const int INF = 0x3f3f3f3f; int X,Y; struct pp { int to,next; }pic[SIZE_B]; int e,head[SIZE_D]; void init() { e = 0; memset(head,-1,sizeof(head)); } void addedge(int x,int y) { pic[e].to = y; pic[e].next = head[x]; head[x] = e++; } const int alter = 1300; int dp[SIZE_D][SIZE_D][SIZE_B]; int finalres,sum; int dfs(int white,int black,int all) { if (dp[white][black][alter+all]!= -INF){ return dp[white][black][alter+all]; } int res = -INF; for (int i = head[white]; i != -1; i = pic[i].next){ int v = pic[i].to; dfs(v,black,all + digit[v]); if (res <= -dp[v][black][alter+all + digit[v]]){ res = -dp[v][black][alter+all + digit[v]]; if (white == X && black == Y){ if (finalres < res){ finalres = res; sum = 1; }else if (finalres == res){ sum++; } } } res = max(res,-dp[v][black][alter+all + digit[v]]); } //printf("1st res = %d\n",res); for (int i = head[black]; i != -1; i = pic[i].next){ int v = pic[i].to; dfs(white,v,all - digit[v]); if (res <= -dp[white][v][alter+all- digit[v]]){ res = (-dp[white][v][alter+all- digit[v]]); if (white == X && black == Y){ if (finalres < res){ finalres = res; sum = 1; }else if (finalres == res){ sum++; } } } } if (res == -INF){ res = -all; if (white == X && black == Y) sum = 1; } return dp[white][black][alter+all] = res; } int main() { int N,M; while (~scanf("%d %d %d %d",&N,&M,&X,&Y)){ for (int i = 0; i < N; i++) scanf("%d",&digit[i]); init(); for (int i = 0; i < M; i++){ int tempx,tempy; scanf("%d %d",&tempx,&tempy); addedge(tempx,tempy); } for (int i = 0; i <= N; i++) for (int j = 0; j <= N; j++) for (int k = 0; k < SIZE_B-1; k++) dp[i][j][k] = -INF; sum = 0; finalres = -INF; dfs(X,Y,1); printf("%d %d\n",finalres,sum); } return 0; }
G题:有个妹子每天住在一个地方,她可以获得一定的收益,每一天得到的钱不同,然后她可以搬到指定的地方numi,那个地方的人类可以帮她搬,但是这个人类搬到某个指定的地方,妹子就要请这个人吃饭,花费指定的钱数bgmi,问妹子在d天晚上之前可以得到的最大钱数。
题解:dp[i][j][k] .i代表这是第i天下午,j代表今晚准备住在j号房子,k代表今晚住完了之后,累计在j住了k天。注意,一定能够要清楚dp中每一维代表的是今晚的情况还是昨晚的情况,很容易纠结不清。
然后这题有个巨大的问题。就是妹子一个下午可以搬家很多很多次啊!天啊,要跑一遍弗洛伊德得出每两个点的最小花费啊!注意正常的弗洛伊德,自己到自己的花费是0,但这道题自己到自己的花费要初始化成INF哟!然后和其他点等同,假如跑了一圈回到自己,那么今晚就相当于第1天而不是第k+1天。
弗洛伊德模板!注意不同问题有不同的初始化方法!!!
int d[SIZE_N][SIZE_N]; void warshall_floyd(int V) { for (int k = 0; k < V; k++) for (int i = 0; i < V; i++) for (int j = 0; j < V; j++) d[i][j] = min(d[i][j],d[i][k] + d[k][j]); }
这道题的ac代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define SIZE_N 330
#define INF 0x3f3f3f3f
using namespace std;
int a[SIZE_N][5],b[SIZE_N],c[SIZE_N],dp[SIZE_N][SIZE_N][5];
int m[SIZE_N][SIZE_N][5];
int mnum[SIZE_N];
int d[SIZE_N][SIZE_N]; void warshall_floyd(int V) { for (int k = 0; k < V; k++) for (int i = 0; i < V; i++) for (int j = 0; j < V; j++) d[i][j] = min(d[i][j],d[i][k] + d[k][j]); }
int main()
{
//freopen("input.txt","r",stdin);
int n,day;
while (~scanf("%d %d",&n,&day)){
memset(d,INF,sizeof(d));
for (int i = 0; i < n; i++){
scanf("%d %d %d",&a[i][1],&a[i][2],&a[i][3]);
a[i][4] = a[i][3];
//int m;
scanf("%d",&mnum[i]);
for (int j = 0; j < mnum[i]; j++){
scanf("%d %d",&m[i][j][0],&m[i][j][1]);
d[i][m[i][j][0]] = m[i][j][1];
}
}
memset(dp,-1,sizeof(dp));
warshall_floyd(n);
//dp[0][0][0] = 0;
dp[1][0][1] = 0;//a[0];//下午还是0的
for (int i = 1; i <= day; i++)
for (int j = 0; j < n; j++)
for (int k = 1; k <= 4; k++){
if (dp[i][j][k] == -1) continue;
//printf("\n\n i = %d j = %d k = %d\n",i,j,k);
int now = dp[i][j][k] + a[j][k];//当前收益
for (int l = 0; l < n; l++){
if (now < d[j][l]) continue;
dp[i+1][l][1] = max(now - d[j][l], dp[i+1][l][1]);
}
if (k <= 3){
dp[i+1][j][k+1] = max(now,dp[i+1][j][k+1]);
}else{
dp[i+1][j][4] = max(now,dp[i+1][j][4]);
}
}
int sum = 0;
for (int j = 0; j < n; j++)
for (int k = 1; k <= 4; k++)
sum = max(sum, dp[day][j][k]);
printf("%d\n",sum);
}
return 0;
}
J题:模拟题。
注意的地方:“namely shifting amnesty for yellow cards from the end of the first round until after the quarter-finals
instead”
首先 四分之一决赛指的是倒数第三场……好吧……决赛<——半决赛<——四分之一决赛……
然后,这句话的 意思是指进入第五场时,前三场的黄牌就可以自动消失,第四场的黄牌保留。
还有,题目中也没说给的比赛号码是按顺序的。
以上。但我根本没做这道题,反正我模拟题的姿势渣的一比。
B题:有四种反转方案,只要你选择一种能经过最少次这种翻转可以得到全白的界面,如果有多种选择序号最小。
题解:首先弄一个可爱的矩阵,三行的。枚举每个方块出现的位置,也就是k从0到1<<15。只要k中哪个位置有1,就代表这个位置转一次。然后,注意有很多都是右侧一列最中间只有一个1的,把他们集体逆时针90度,然后只需要遍历第一行就知道放还是不放啦。
存矩阵的时候把每个角度都转一遍存下来~一共存四个矩阵,然后每个矩阵一行的十五个数字压缩成二进制表示一个数字。然后每种方法放的时候遍历第一行就好啦。
存方法数矩阵的时候有一个特别厉害的姿势可以存下k从0到1<<15中所有的矩阵。
所有的都逆时针九十度了所以记得原矩阵也要逆时针90度。
相关文章推荐
- Windows Azure存储共享配置介绍
- 黑马程序员—IOS之C语言基础—循环结构与分支结构
- poj1251(prime()+读取字符bug)
- 用express、mongodb、nodejs开发简单的登陆
- hbase环境搭建,启动之后HMaster挂掉,或者是集群里,只启动了HMaster节点,HRegionServer节点没有启动的问题
- [LeetCode]Remove Linked List Elements
- ApplicationContext的三种实现方式以及在web.xml配置的两种方式
- [BZOJ1085][SCOI2005]骑士精神
- Picasso:一个强大的图片下载和缓存库
- C Language Study - gets , getchar & scanf
- 我想做一个合格的工程师
- Exchange Server 2013 公网发布疑难解答
- 猜拳小游戏过程以及感悟
- [BZOJ2456]mode
- Ninject依赖注入——构造函数、属性、方法和字段的注入
- 解决The current branch is not configured for pull No value for key branch.master.merge found in config
- FreeBSD 10添加Swap文件
- eclipse连接hbase异常KeeperErrorCode = ConnectionLoss for /hbase/meta-region-server
- hdu1072(bfs搜索退出的条件有变)
- [BZOJ1798][Ahoi2009]Seq 维护序列seq