2024/11/30課堂記錄

永韶發表於2024-11-30

目錄

1. 機器分配

2.最大食物鏈計數

3.菜餚製作


  • 機器分配
多重揹包變式,改變一下計算價值的方式

另外,題目裡沒提到要前面的公司儘量少分配,後面的公司儘量多分配,不然90分
所以比較時要<=(20行)
見程式碼,寫註釋了

點選檢視程式碼
#include<iostream>
using namespace std;
int a[20][20],f[20][20],b[20][20];
void out(int n,int m)
{
	if(n==0) return;
	out(n-1,m-b[n][m]);//先輸出前面的,前面要用n-1個公司分 m-b[n][m]臺機器 
	cout<<n<<" "<<b[n][m]<<"\n";
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>a[i][j];
	for(int i=1;i<=n;i++)//第i家到來 
		for(int j=1;j<=m;j++)//只給i以前的j臺機器 
			for(int k=0;k<=j;k++)//可以不分配,從0開始,不能超過j 
				if(f[i][j]<=f[i-1][j-k]+a[i][k])//滿足隱藏條件 
					f[i][j]=f[i-1][j-k]+a[i][k],b[i][j]=k;//總工j臺,前面i-1家給j-k臺,第i家給k臺 
	cout<<f[n][m]<<"\n";
	out(n,m);
	return 0;
}

  • 最大食物鏈計數

很經典的一道鏈式前向星+拓撲

理解難度不大,不開longlong見祖宗

點選檢視程式碼
#include<iostream>
using namespace std;
int r[5050],c[5050];//入度出度 
long long int f[5050];//每個點之後最大值 ,不開longlong見祖宗 
int stack[5050],top;//藉助棧,top指向最高儲存格 
long long int sum;//不開longlong見祖宗 
//以下為鏈式前向星標準模版 
struct EDGE
{
	int next,to;
}edge[500500];
int head[5050],tot; 
void add(int from,int to)
{
	edge[++tot].next=head[from];
	edge[tot].to=to;
	head[from]=tot;
}
//以上為鏈式前向星標準模版 
int main()
{
	int n,m;
	cin>>n>>m;
	while(m--)
	{
		int a,b;
		cin>>a>>b;
		add(b,a);//反向建圖,與生物學相反,吃->被吃 
		c[b]++;
		r[a]++;
	}
	for(int i=1;i<=n;i++)
		if(r[i]==0)//最高階消費者 
			stack[++top]=i,f[i]=1;//入棧,代表一個終點
	while(top)
	{
		int from=stack[top--];
		for(int i=head[from];i;i=edge[i].next)
		{
			int to=edge[i].to;
			f[to]+=f[from]%80112002;//累計方案數
			r[to]--;//刪邊 
			if(r[to]==0)//變成了最高階消費者 
			{
				stack[++top]=to;//入棧 
				if(c[to]==0)//如果又是生產者 
					sum+=f[to]%80112002;//累計答案 
			}
		}
	}
	cout<<sum%80112002;
	return 0; 
} 

  • 菜餚製作

鏈式前向星,反向建圖,拓撲,反向儲存輸出,理解難度大,優先佇列

暫時沒完全看懂,但看懂收穫一定很大

點選檢視程式碼
//https://www.luogu.com.cn/problem/solution/P3243
//菜餚製作-拓撲排序3 
//反向建圖+最大字典序 
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#define ll long long
#define INF 0x7fffffff

using namespace std;

priority_queue<int>que;  //預設大根堆 

int t,n,m,x,cnt,d[100005],k[100005],ans[100005];

struct Edge
{
	int to,next;
}edge[100005];

struct node{
	int x,y;
}u[100005];

void add(int x,int y)
{
	edge[++cnt].to = y;
	edge[cnt].next = d[x];
	d[x] = cnt;
	k[y] ++;
}

/*
int mysort(node a,node b) 
{
    return a.y < b.y;
}
*/ 

void clean()
{
	while(!que.empty()) 
	    que.pop();
}

void work()
{
	for(int i = 1; i <= n; i++) 
	    if(k[i] == 0) 
		    que.push(i);
	while(!que.empty())
	{
		x = que.top();
		ans[++cnt] = x;
		que.pop();
		for(int i = d[x]; edge[i].to != 0; i = edge[i].next)
		{
			k[edge[i].to] --;
			if(k[edge[i].to] == 0) 
			    que.push(edge[i].to);
		}
	}
}

int main()
{
	scanf("%d",&t);
	for(int a = 1; a <= t; a++)
	{
		cnt = 0;
		memset(d,0,sizeof(d));
		memset(k,0,sizeof(k));
		clean();
		scanf("%d%d",&n,&m);
		for(int i = 1; i <= m; i++) 
		    scanf("%d%d",&u[i].x,&u[i].y);
		for(int i = 1; i <= m; i++) 
		    add(u[i].y,u[i].x);
		cnt = 0;
		work();
		if(cnt < n) 
		    printf("Impossible!");
		else
		for(int i = n; i >= 1; i--) 
		    printf("%d ",ans[i]);
		printf("\n");
	}
    return 0;
}

相關文章