这次比赛成绩考得不咋地,第一次做C组就被水淹了,滚粗。。。QAQ。。。
一开始是抱着快点做完题去改题的心态去做比赛的,于是当时考场只打了前两题,而且还没有打拍,这很不应该,后两题只是略加思索,并没有实现。。。于是乎。。。就垫底了。。。
题解T1 小猫爬山
【NOIP2013模拟】小猫爬山 (Standard IO)
Time Limits: 1000 ms Memory Limits: 131072 KB Detailed Limits
Description
Freda和rainbow饲养了N只小猫,这天们要去爬山 。经历了千辛万苦,小猫们 终于爬上了山顶,但是疲倦的它们再也不想徒步走下(呜咕 ><>< )。
Freda 和 rainbow只好 花钱让它们坐 索道 下山。 索道 上的缆车 最大承重量为 W,而 N只 小猫的重量分别是 C1、C2…… CN。当然,每辆缆车上的小猫重量之和不能超过W。每 租用一辆缆车 ,Freda 和 rainbow 就要付 1美元 ,所以他们想知道,最少需要付 多少美元才 能把这 N只小猫都运送下山?
Input
第一行 包含两个用空格隔开的整数, N和 W。
接下来 N行每一个整数,其中第 i+1行的整数 表示第 i只小猫的重量 Ci。
Output
输出 一个整数,最少需要多美元也就是辆缆车 。
Sample Input
5 1996
1
2
1994
12
29
Sample Output
2
Data Constraint
对于100%的数据,1<=N<=18,1<=Ci<=W<=10^8
乍一看,以为这道题是道DP,仔细想过后可以用迭代深搜实现。
首先,最好的情况自然是
所以我们可以从sum~18开始枚举车辆,进行深搜dfs。(因为最坏的情况也只是18辆)。
深搜过程我们可以用一个F数组记录每一种情况是否可行进行剪枝。
CODE
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fd(i,a,b) for (int i=a;i>=b;i--)
#define N 20
using namespace std;
int c[N],F[N],sum=0,tot=0,n,w;
bool bz=false;
inline int read(int &number)
{
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') number=number*10+ch-'0',ch=getchar();
return number;
}
bool cmp(int x,int y)
{
return x>y;
}
void dg(int x)
{
if (x==n+1)
{
bz=true;
return;
}
fo(i,1,tot)
if (F[i]+c[x]<=w)
{
F[i]+=c[x];
dg(x+1);
F[i]-=c[x];
if (bz) return;
}
return;
}
int main()
{
read(n);read(w);
fo(i,1,n)
{
read(c[i]);
sum+=c[i];
}
sort(c+1,c+n+1,cmp);
for (tot=sum/w;tot<=18;tot++)
{
dg(1);
if (bz)
{
printf("%d\n",tot);
return 0;
}
}
return 0;
}
T2
【NOIP2013模拟】KC看星 (Standard IO)
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
Description
“一闪一闪亮晶晶,满天都是小星星”
Kc吟唱着歌谣,躺在草坪上边想着她边看起了星星。Kc刚刚结识了笛卡尔这位好基友,认为他的坐标系非常神奇。于是他随机地选出了8颗星星,并且给它们标上了坐标。Kc又不甘寂寞,于是思考起一个问题:这八个点能否恰好构成一个正方形和一个矩形呢?
Input
输入文件包括1行16个数,表示8个星星的坐标,坐标绝对值不超过10000。
Output
输出文件第一行是”YES”或者”NO”。表示是否有解。
若有解则第二行依次输出正方形每个顶点的序号。第三行依次输出矩形每个顶点的序号。序号即为输入的顺序。
另外注意:因为kc是一个刁端的人,所以他要求第二行和第三行这八个数要字典序最小。
四点共线不能认为是正方形或矩形
Sample Input
0 0 10 11 10 0 0 11 1 1 2 2 2 1 1 2
Sample Output
YES
5 6 7 8
1 2 3 4
题解:
其实这道题只要模拟一下判断正方形和矩形的特性就可以了。注意斜着的正方形和矩形也算合法矩形,还有用c++同学和他的读入优化的同学请注意了,读入优化貌似不能读入负数,TMD的我就是这样被坑了。。。苍白无力。。,
-正方形判定可以用四边相等,对角线相等。
-举行判定可以用两组对边分别相等,对角线相等。
CODE
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fd(i,a,b) for (int i=a;i>=b;i--)
#define N 10
using namespace std;
int a[N][3],b[N][N],c[N];
bool Mark[N];
void dg(int x)
{
if (x==8+1)
{
bool bz1=false;
bool bz2=false;
if (b[c[1]][c[2]]==b[c[3]][c[4]])
if (b[c[1]][c[3]]==b[c[2]][c[4]])
if (b[c[1]][c[2]]==b[c[1]][c[3]])
if (b[c[1]][c[4]]==b[c[2]][c[3]]) bz1=true;
if (b[c[5]][c[6]]==b[c[7]][c[8]])
if (b[c[5]][c[7]]==b[c[6]][c[8]])
if (b[c[5]][c[8]]==b[c[6]][c[7]]) bz2=true;
if (bz1 && bz2)
{
fo(i,1,3)
fo(j,i+1,4)
if (c[i]>c[j])
swap(c[i],c[j]);
fo(i,5,7)
fo(j,i+1,8)
if (c[i]>c[j]) swap(c[i],c[j]);
printf("YES\n");
fo(i,1,4) printf("%d ",c[i]);
printf("\n");
fo(i,5,8) printf("%d ",c[i]);
exit(0);
}
return;
}
fo(i,1,8)
if (!Mark[i])
{
c[x]=i;
Mark[i]=true;
dg(x+1);
Mark[i]=false;
}
}
int main()
{
fo(i,1,8) scanf("%d",&a[i][1]),scanf("%d",&a[i][2]);
memset(b,0,sizeof(b));
fo(i,1,8)
fo(j,1,8)
if (i!=j)
b[i][j]=sqrt((a[i][1]-a[j][1])*(a[i][1]-a[j][1])+(a[i][2]-a[j][2])*(a[i][2]-a[j][2]));
fo(i,1,8)
{
Mark[i]=true;
c[1]=i;
dg(2);
Mark[i]=false;
}
printf("NO\n");
return 0;
}
T3
【NOIP2013模拟】KC的瓷器 (Standard IO)
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
Description
KC来到了一个盛产瓷器的国度。他来到了一位商人的店铺。在这个店铺中,KC看到了一个有n(1<=n<=100)排的柜子,每排都有一些瓷器,每排不超过100个。那些精美的艺术品使KC一下心动了,决定从N排的商品中买下m(1<=m<=10000)个瓷器。
这个商人看KC的脸上长满了痘子,就像苔藓一样,跟精美的瓷器相比相差太多,认为这么精致的艺术品被这样的人买走艺术价值会大打折扣。商人感到不爽,于是规定每次取商品只能取其中一排的最左边或者最右边那个,想为难KC。
现在KC又获知每个瓷器的价值(用一个不超过100的正整数表示),他希望取出的m个商品的总价值最大。
Input
输入文件的第一行包括两个正整数n,m;
接下来2到n+1行,第i行第一个数表示第i排柜子的商品数量Si,接下来Si个数表示从左到右每个商品的价值。
Output
输出文件只有一个正整数,即m个商品最大的总价值。
Sample Input
输入1:
2 3
3 3 7 2
3 4 1 5
输入2:
1 3
4 4 3 1 2
Sample Output
输出1:
15
样例解释1:
取第一排的最左边两个和第二排的最右边那个。总价直为3+7+5=15;
输出2:
9
Data Constraint
对于10%的数据,Si=1,1<=i<=n。
对于另外10%的数据,n=1.
这是一道Dp题,题解是这样写的,
先预处理
考虑对于每一排取出最左边的k个,那么剩下的j-k个就是最右边的,1<=k<=c。易得:
接下来进行动态规划,
那么
其实可以优化上述Dp,我们可以发现有一些状态是可以重复利用的,可以用滚动数组
CODE
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define N 105
#define Maxn 10005
using namespace std;
int a[N],Pre[N],F[2][Maxn];
inline int read()
{
char ch=getchar();
int number=0;
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') number=number*10+ch-'0',ch=getchar();
return number;
}
int main()
{
int n,m,tot=0;
n=read();
m=read();
fo(i,1,n)
{
tot=read();
fo(j,1,tot) a[j]=read();
fill(Pre,Pre+N,0);
fo(j,1,tot) Pre[j]+=Pre[j-1]+a[j];
int tqy=(i&1);
int cqy=((i+1)&1);
fo(i,1,m) F[tqy][i]=F[cqy][i];
fo(j,1,tot)
{
int tmp=0;
fo(k,0,j) tmp=max(tmp,Pre[k]+Pre[tot]-Pre[tot-j+k]);
fo(k,j,m)
{
int lqy=F[cqy][k-j]+tmp;
F[tqy][k]=max(F[tqy][k],lqy);
}
}
}
printf("%d",F[n&1][m]);
return 0;
}
T4
【NOIP2013模拟】开心小屋 (Standard IO)
Memory Limits: 262144 KB Detailed Limits
Description
Kc来到开心小屋。开心小屋是用来提升心情的。在这个小屋中有n个房间,一些房间之间有门连通。从房间i到达房间j,心情值可以加上-10000<=Cij<=10000,当然Cij可能是负的。现在kc失恋了,所以他想要知道他是否可以在这个小屋中无限地增加他的心情值,也就是无限地绕着一个环走?
请帮kc求出最小的环需要经过的房间数,来使他的心情无限增加。
Input
第一行给出,1<=n<=300,1<=m<=5000。分别表示房间数及门的数量。
接下来m行,每行四个数:i,j,Cij,Cji
Output
输出文件包括一行,及最小的环需要经过的房间数。
保证不会出现自环及重边。
Sample Input
4 4
1 2 -10 3
1 3 1 -10
2 4 -10 -1
3 4 0 -3
Sample Output
4
样例解释:
1—>3—>4–>2–>1为最小的符合题意的环长度为4.
Data Constraint
对30%的数据,n<=10;
对60%的数据,,n<=100;
对100%的数据,n<=300;
题解:题目其实就是说给出无向图,要求求出节点数最小的正环长度。
可以用深搜来实现
正解说用弗洛伊德预处理出f[p][i][j],表示从i到j经过2^p条路径的最长路径。
接着二分答案t。检验答案和预处理类似,只需要考虑二进制位上为1的位置就可以了。用g[z][i][j]表示处理到第z个二进制位上为1的位置从i到j的最长路径,转移方程为:
时间复杂度O(n^3log^2n),会超时。
关于100%的数据,还没有理解透,等到时在更新。
至于CODE。。我还没打。。。年轻人自己思考吧。。。
这次比赛暴露出的问题有:
1、比赛没有对拍,导致该拿的分没有拿到,本来ac的两道题就飞了,没有仔细检查程序,对自己的程序太自信了。下次要好好应对每场比赛,每一道题,确保无误再交题。
2、考试太急了,还没有仔细思考就开打,导致后面思路凌乱。
3、要沉下心打题,遇到一些麻烦的打法要好好看,不能三心二意。
4、这次GG炸飞掉了,有很大原因是没有好好打题,轻视了这次比赛,最后还被别人虐了。。。狗带。。。
总结
1、每一场比赛都不能轻视
2、要好好总结,提高自己程序实践能力
3、心态要良好
4、%%%大神