1. 程式人生 > >NOIP普及組板子及注意事項

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