Perform

甚至在打标题的时候还打成了preform
怪不得比赛打preform了

题面

题解:
非常水的一个DP
定义\(i\)为第\(i\)个城市,\(j\)为第\(j\)天,\(l\)为上一天从\(l\)城市到达\(i\)
接着是循环:
\(j\)天从\(l\)到达\(i\),是通过\(l\)\(j-1\)天的航班飞过来
显然应当是\((j-1)\bmod sum_l\)
如果\(sum_l\)\(0\)说明没有这一航班自然就不能转移

状态转移方程:
f[i][j]=min(f[i][j],f[l][j-1]+a[l][i].t[(j-1)%a[l][i].sum+1]);
初值:
\(f[1][0]=0\),其他\(-INF\)
目标:\(f[n][k]\)
然后就是先枚举天数再枚举城市,这样没后效性

数据范围小到暴搜都能过

然后就是注意多测

点击查看代码
#include <bits/stdc++.h>
using namespace std;
int n,k,ans=0x3f3f3f3f;
int f[22][2222];
struct node {
	int sum;
	int t[30];
}a[20][20];
int read(){
	int i=1,j=0;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			i=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		j=j*10+ch-48;
		ch=getchar();
	}
	return i*j;
}
void in(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(j==i){
				continue;
			}
			a[i][j].sum=read();
			for(int k=1;k<=a[i][j].sum;k++){
				a[i][j].t[k]=read();
			}
		}
	}
}
void work(){
	memset(f,0x3f,sizeof(f));
	f[1][0]=0;
	for(int j=1;j<=k;j++){
		for(int i=1;i<=n;i++){
			for(int l=1;l<=n;l++){
				if(i==l){
					continue;
				}
				else if(a[l][i].t[(j-1)%a[l][i].sum+1]==0){
					continue;
				}
				else{
					f[i][j]=min(f[i][j],f[l][j-1]+a[l][i].t[(j-1)%a[l][i].sum+1]);
				}
			}
		}
	}
}
void out(){
	ans=f[n][k];
	if(ans==0x3f3f3f3f)ans=0;
	cout<<ans<<endl;
}
void renew(){
	memset(a,0,sizeof(a));
	ans=0x3f3f3f3f;
}
int main(){
	freopen("perform.in","r",stdin);
	freopen("perform.out","w",stdout);
	while(scanf("%d%d",&n,&k)!=EOF){
		if(n==0&&k==0){
			break;
		}
		in();
		work();
		out();
		renew();
	}
	return 0;
}
posted @ 2022-06-07 18:20  2K22  阅读(380)  评论(0)    收藏  举报