NOIP普及组板子及注意事项

转载至 w y c wyc 大佬

介绍:应aj咳咳咳,(搞错了,重来!)
应教练要求, w y c wyc 写给学弟们的

板子


//01背包模版
#include<cstdio>
using namespace std;
int n,m,a[101],f[10001];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
      scanf("%d",&a[i]);
    f[0]=1;
    for(int i=1;i<=n;i++)
      for(int j=m;j>=a[i];j--)
        f[j]+=f[j-a[i]];
    printf("%d",f[m]);
}

//完全背包模版
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,w[501],c[501],s[501],f[6001];
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) 
	  scanf("%d%d%d",&w[i],&c[i],&s[i]);
	for (int i=1;i<=n;i++)
	  for (int j=m;j>=0;j--)
	    for (int k=0;k<=s[i];k++)//枚举组数
	    {
	    	if (j-k*w[i]<0) break;//判断越界
	    	f[j]=max(f[j],f[j-k*w[i]]+k*c[i]);
	    }
	printf("%d",f[m]);
}

//二进制优化
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,w[10001],c[10001],f[6001],n1;
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) 
	{
	  int x,y,s,t=1;
	  scanf("%d%d%d",&x,&y,&s);
	  while (s>=t)
	  {
	  	w[++n1]=x*t;
	  	c[n1]=y*t;
	  	s-=t;
	  	t*=2;
	  }
	  w[++n1]=x*s;
	  c[n1]=y*s;
	  //二进制优化
	}
	for (int i=1;i<=n1;i++)
	  for (int j=m;j>=w[i];j--)
	    f[j]=max(f[j],f[j-w[i]]+c[i]);
	printf("%d",f[m]);
} 

//混合背包
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,w[31],c[31],f[201],s[31];
int main()
{
	scanf("%d%d",&m,&n);
	for (int i=1;i<=n;i++) 
	{
	  scanf("%d%d%d",&w[i],&c[i],&s[i]);
	}
	for (int i=1;i<=n;i++)
	  if (s[i]==0)
	  {
	  	for (int j=w[i];j<=m;j++)
	  	  f[j]=max(f[j],f[j-w[i]]+c[i]);
	  }//完全背包
	  else
	  {
	  	for (int j=1;j<=s[i];j++)
	  	  for (int k=m;k>=w[i];k--)
	  	    f[k]=max(f[k],f[k-w[i]]+c[i]);
	  }//多重
	printf("%d",f[m]);
}

//分组背包
#include<cstdio>
#include<iostream>
using namespace std;
int w[31],c[31],a[11][32],f[201],m,n,t,p;
int main()
{
	scanf("%d%d%d",&m,&n,&t);
	for (int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&w[i],&c[i],&p);
		a[p][++a[p][0]]=i;//分组
	}
	for (int i=1;i<=t;i++)
	  for (int j=m;j>=0;j--)
	    for (int k=1;k<=a[i][0];k++)
	    //枚举选的组数
	      if (j>=w[a[i][k]])//避免越界
	      {
	      	f[j]=max(f[j],f[j-w[a[i][k]]]+c[a[i][k]]);
		//动态转移
	      }
	printf("%d",f[m]);
}

//快速幂模版 
#define ll long long
int power(int a,int b)
{
	int ans=1;
	a%=p;//不这样很可能会炸 
	while(b)
	{
		if(b&1) ans=(ll)ans*a%p; 
		a=(ll)a*a%p
		//记得加(ll)
	}
	return ans;
}

//二分查找
int find(int a[],int x) //在a中查找x
{
	int l=1,r=n;//假设a数组下标为1..n
	//并且a单调递增,简单来说就是前面的比后面的小  
	while(l<=r)
	{
		mid=(l+r)/2;//取中间值
		if(a[mid]==x) return mid;//找到了! 
		if(a[mid]<x)//取的值比x小,那么我们要往右边走
		l=mid+1;
		else //否则,我们要往左边走
		r=mid-1; 
	}
	return ("找你mb",0);
}

//快速读入,使用方法 x=read()
int read() 
{
	int x=0,flag=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*flag;
}

//快速输出
void write(int x)
{
    if(x<0) {x=-x;putchar('-');}
	if(x>9) write(x/10);
	putchar(x%10+48);
	return;
}

//Lu某同学要的结构体排序 
#include<algorithm>
struct node{
	int x,b,gezhongdongxi;
}a[N];
bool cmp(node x,node y)
{return x.x>y.x;}
//根据x从大到小排序 
void sort_MB()
{
	sort(a+1,a+1+n,cmp);
	//从1~n排序 
}

//gcd(求最大公约数)模版
int gcd(int a,int b)
{
	if(!b) return a;
	return gcd(b,a%b);
}

//杨辉三角递推
void ycl_get()//预处理 
{
	c[0][0]=1;
	for(int i=1;i<=N;i++)
	  for(int j=1;j<=N;j++)
	    c[i][j]=c[i-1][j]+c[i-1][j-1];
}
//求组合数(配合上面使用) 
int get_C(int x,int y)
{return c[x+1][y+1];}

//随机l~r的数字
#incldue<cstdlib>
#define random(l,r) l+rand()%(r-l+1)

//对拍程序模版(选学)
#include<windows.h>
#include<ctime>
void dp()//dp==对拍 
{
	while(1)
	{
		system("data.exe");//运行随机程序 
		system("BL.exe");//运行暴力
		double st=clock(); 
		system("MPY.exe");//运行(伪)正解 
		double ed=clock();
		if(system("fc data.ans data.out")){
		    printf("傻逼了吧,你的(伪)正解WA了");
		    return;
		}
		else
		  printf("(暂时)AC time:%0.2lf ms",ed-st); 
	}
}

//algorithm库的骚操作
#include<algorithm>
void std()
{
	wz=lower_bound(a+1,a+1+n,x)-(a+1)
	//在a数组中查找x的位置(如果不存在,返回前面那个数的位置),返回到wz
	m=unique(a+1,a+1+n)-(a+1);
	//将a数组去重(要求a数组已经排好序),剩下的元素个数返回到m
	fill(a+1,a+1+n,x);
	//将a数组下标为1..n的都赋值为x,类似memset,但可以限制范围
	//如若要清空n*m的二维数组,格式如下
	fill(a[1]+1,a[n]+1+m,0);
	//不过推荐你们还是用memset清空好,不容易错
	//但这种方法对于不是清0的时候很好用! 
}

//other骚操作
void sao()
{
	for(register int i=1;i<=n;++i)
	//++i比i++快, 循环变量前加register会更快
	a<<b//a*(2^b)快速运算
	putchar();//用putchar()输出单个字符更快
	//用字符数组处理比字符串会优秀 
	//更多的详见你们学长的博客
	//https://blog.csdn.net/xuxiayang/article/details/81021585 
	//——to be continue 
}

//输出数组内存
printf("%.3f M\n",(double)sizeof(a)/(1<<20));
printf("%.3f K\n",(double)sizeof(a)/(1<<10));

//(你们)常用的头文件
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
//以下的最好不要放在要交的程序里 
#include<cstdlib>
#include<ctime> 
//以下的千万不要放在要交的程序里
#include<windows.h> 
//前面带"__"的函数不可以用 

可能有些写错了(反正我也没编译过)。
不会的来问我。


注意事项

之后是来自菜鸡学长的一些提醒

  1. 做不出来题目心态不要爆炸,反正你做不出来别人也做不出来
  2. 不会的就暴力,暴力出奇迹
  3. 上面的板子都背好,总会有用的
  4. 头文件起码检查10遍以上(特别是Wu同学)
  5. 记得看要不要用 l o n g l o n g long long
  6. 第四题你们应该都是做不出来的,水个几十分就好了
  7. 前2题一定要对,不然你基本凉了╮(╯_╰)╭
  8. 写大模拟题的时候我推荐你们给自己的代码加注释

经历分享

//以下是 w y c wyc 去年第3题的程序

while (true)
{
    if (x+1==n && y==n && color[n][n]==c || x==n && y+1==n && color[n][n]==c || x==n && y==n) break;
    else if (x+1==n && y==n && color[n][n] || x==n && y+1==n && color[n][n]) {money++; break;}
    else if (x+1==n && y==n || x==n && y+1==n) {money+=2; break;}
    else if (color[x][y+1]==c) y++;
    else if (color[x+1][y]==c) x++;
    else if (color[x-1][y]==c) x--;
    else if (color[x][y-1]==c) y--;
    else if (color[x][y+1]) {money++;y++;c=color[x][y];}
    else if (color[x+1][y]) {money++;x++;c=color[x][y];}
    else if (color[x][y-1]) {money++;y--;c=color[x][y];}
    else if (color[x-1][y]) {money++;x--;c=color[x][y];}
    else if (color[x+1][y+1]==c) {money+=2;x++;y++;}
    else if (color[x+2][y]==c) {money+=2;x+=2;}
    else if (color[x][y+2]==c) {money+=2;y+=2;}
    else if (color[x+1][y+1]) {money+=3;x++;y++;c=color[x][y];}
    else if (color[x+2][y]) {money+=3;x+=2;c=color[x][y];}
    else if (color[x][y+2]) {money+=3;y+=2;c=color[x][y];}
    else if (color[x-1][y-1]==c) {money+=2;x--;y--;}
    else if (color[x-2][y]==c) {money+=2;x-=2;}
    else if (color[x][y-2]==c) {money+=2;y-=2;}
    else if (color[x-1][y-1]) {money+=3;x--;y--;c=color[x][y];}
    else if (color[x-2][y]) {money+=3;x-=2;c=color[x][y];}
    else if (color[x][y-2]) {money+=3;y-=2;c=color[x][y];}
    else {printf("-1");return 0;}
    color[x][y]=0;
}

其实开始只有几行 i f if ,然后根据数据慢慢的变多了 i f if
其实贪心可以不断优化(我 T M TM 都不知道去年怎么写出来的)
题目链接

残酷的事实----省赛
你们应该只有这次考得最好的才有可以去省赛
这真的是一个很好的历练机会
而且会使你变的特别有梦想,
你们都要争取机会!
—— w y c wyc


推荐习题

考前看看有没有时间做一下这些题
2017 T3
2016 T3
2015 T3
2015 T4
2014 T3
2013 T3
2013 T2
2012 T3
如果都能A那么你稳一等了

话说你们可以加一下你们菜鸡学长的luogu团队
https://www.luogu.org/team/show?teamid=6849
有挺多适合你们的模拟题的(我们自己出的)


网站推荐

https://visualgo.net/zh
算法可视化,以后学算法的时候对于理解很有用

http://latex.codecogs.com/eqneditor/editor.php
公式编辑器,写博客的时候可能要用到

https://www.processon.com/i/5afc24e5e4b02ec429d1c896

https://www.processon.com/i/5afc01e3e4b096c6eeb3834b
流程图制作

http://oeis.org/
序列查找器,用于各种找规律

https://yhx-12243.github.io/OI-transit/index.html?curLoc=Local
优秀的东西

http://www.noi.cn/
NOI官网

https://www.luogu.org/blog/w-2-3-c-3-c-3/oi-suan-fa
算法大全

好了就这么多

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/83659461