Timetable-DP-CF946D(好题)

本文介绍了一种使用动态规划(DP)算法解决特定课程安排问题的方法。通过计算跳过不同数量课程所需的最短时间,该算法能够在给定的课程表中找到最优的跳课策略,以最小化学生在校总时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目传送门
思路:
DP

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<cstring>
#include<string>
#include<cmath>

using namespace std;

typedef long long LL;

#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i = a;i <= b;++i)
#define rep(i,a,b) for(int i = a;i >= b;--i)
const int maxn =  5e2;
int n = 0,m = 0,k = 0; 
vector<int> vt[maxn+10];
char s[maxn+10];
int num[maxn+10][maxn+10];//num[i][j]表示第i天跳过j个课后待在学校的最短时间 
int dp[maxn+10][maxn+10];//dp[i][j]表示前i天跳过了j个课后待在学校的最短时间 
int main(){
	//std::ios::sync_with_stdio(false);
	while(~scanf("%d %d %d",&n,&m,&k)){
		per(i,1,n){
			vt[i].clear();
		}
		memset(dp,0,sizeof(dp));
		per(i,1,n){
			scanf("%s",s+1); 
			per(j,1,m){
				if(s[j] == '1'){
					vt[i].push_back(j);
				}
			}
		}
		per(i,1,n){
			int size = vt[i].size();
			if(size == 0){
				continue;
			}
			num[i][size] = 0;//跳过第i天的全部课程 
			per(len,1,size){//先计算第i天上len个课所需要的最短时间 
			//per(len,1,size){
				int minv = vt[i][len-1] - vt[i][0] + 1;
				for(int j = 0;j + len - 1 <= size-1;++j){
					minv = min(minv,vt[i][j+len-1] - vt[i][j] + 1);
				}
				num[i][size-len] = minv;//跳过size-len个课所需的最短时间,就是上len个课所需的最短时间 
			}
		}
		per(i,0,k){
			dp[1][i] = num[1][i];//初始化第一天 
		}
		per(i,2,n){
			per(j,0,k){
				int minv = dp[i-1][j] + num[i][0];
				per(p,1,j){//第i天跳过p个课 
					minv = min(minv,dp[i-1][j-p] + num[i][p]);
				}
				dp[i][j]  = minv;//前i天跳过j个课 
			}
		}
		printf("%d\n",dp[n][k]);
	}
	
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值