动规初学者打分组背包时遇见的奇妙问题
  • 板块学术版
  • 楼主C83_AD
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/4/2 18:04
  • 上次更新2024/4/2 20:03:03
查看原帖
动规初学者打分组背包时遇见的奇妙问题
393852
C83_AD楼主2024/4/2 18:04

事情是这样。我最近在考虑分组背包的事。题如一本通网站上那个标准版子题。这是我两年前的代码:

//标准板子,没必要看了
#include<cstdio>
using namespace std;
int v,n,t,c[33],w[33],p[33],f[203];
int main(){
	scanf("%d%d%d",&v,&n,&t);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&w[i],&c[i],&p[i]);
	}
	for(int i=1;i<=t;i++){
		for(int j=v;j>=1;j--){
			for(int k=1;k<=n;k++){
				if(p[k]==i&&j>=w[k]){
					f[j]=(f[j]>f[j-w[k]]+c[k]?f[j]:f[j-w[k]]+c[k]);
				}
			}
		}
	}
	printf("%d",f[v]);
	return 0;
}

然后我为了让自己看得清楚一些,我改了一些变量名,并且用手打的模拟队列来存组:

//时间复杂度:输入O(n^2),主体O(n*v) 
#include<stdio.h>
using namespace std;
struct lnt{
	int weight,value,next;
}a[33];//每个物品。该结构体是t个链表 
struct dnt{
	int num,head,min;
}group[13];//每组用链表存,用头指针表示组。min存组内重量最小值。 
int v,n,t,x,f[203];
int main(){
	//初始化指针、最小值 
	for(int i=0;i<33;i++) group[i].min=a[i].next=1e9; 
	//输入与链表存组 
	scanf("%d%d%d",&v,&n,&t);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].weight,&a[i].value,&x);
		if(group[x].num==0) group[x].head=i;
		else{
			int next=group[x].head;
			while(a[next].next<1e9) next=a[next].next;
			a[next].next=i;
		}
		group[x].num++;
		if(group[x].min>a[i].weight) group[x].min=a[i].weight;
	}
//	for(int i=1;i<=203;i++) printf("%3d:%d\n",i,f[i]);
	//跑dp 
	for(int i=1;i<=203;i++) f[i]=0;
	for(int i=1;i<=t;i++){
		for(int j=v;j>=group[i].min;j--){
			int next=group[i].head;
			for(int x=1;x<=group[i].num;x++){
				if(j>=a[next].weight){
					if( f[j]<f[j-a[next].weight]+a[next].value){
						f[j]=f[j-a[next].weight]+a[next].value;
					}
				}
				next=a[next].next;
			}
		}
	}
	printf("%d",f[v]);
	return 0;
}

问题就出现了。被我注释的哪行代码如果运行,输出的结果非常的奇怪:

  1 0
  2 1000000000
  3 0
  4 0
  5 1000000000
  6 0
  7 0
  8 1000000000
......
//此后,每个i=2+3*k,出现f[i]=1e9,直到i=50以后。

但是我在这之前完全没有对 数组f 进行任何操作。在本地与云IDE上运行均是这样的结果。为什么会出现这样的情况呢?

输入样例:

10 6 3
2 1 1
3 3 1
4 8 2
6 9 2
2 8 3
3 9 3

敬请您回答。

可能是很弱智的问题。如果是,请提醒我删帖。

2024/4/2 18:04
加载中...