UVALive - 4256 Salesmen DP+暴力

本文介绍了一个基于图论与动态规划(DP)的算法,该算法用于解决在一个给定的无向连通图中寻找最优整数序列的问题。通过定义状态dp[i][j]表示以节点j结束时的最小修改次数,利用状态转移方程实现了高效求解。

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

题目大意:给定一个包含n1个点,n2条边的无向连通图,再给出一个序列长度为n的整数序列A,要求每两个相邻的整数不是相等就是连通,给出的这个序列上的数可以修改,问至少经过多少次的修改可以得到正确的序列

解题思路:暴力枚举每种状态,设dp[i][j]为第i个以j结尾时共修改了多少次,这样就可以得到状态转义方程了

dp[i][j] = min(dp[i][j],dp[i-1][k]+1)这是修改了第i个数的情况

dp[i][j] = min(dp[i][j],dp[i-1][k])这是没有修改第i个数的情况

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn1 110
#define maxn2 210
#define INF 0x3f3f3f3f
int n1, n2, n,  graph[maxn1][maxn1], A[maxn2], dp[maxn2][maxn2];

int main() {
	int test;
	scanf("%d", &test); 
	while(test--) {
		scanf("%d%d", &n1, &n2);
		memset(graph,0,sizeof(graph));
		int x, y;
		for(int i = 0; i < n2; i++) {
			scanf("%d%d",&x, &y);
			graph[x][y] = graph[y][x] = 1;
		}

		for(int i = 1; i <= n1; i++) 
			graph[i][i] = 1;

		scanf("%d",&n);
		for(int i = 1; i <= n; i++) 
			scanf("%d", &A[i]);

		for(int i = 1; i <= n1; i++)
			dp[0][i] = 0;

		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n1; j++) {
				dp[i][j] = INF;
				for(int k = 1; k <= n1; k++) 
					if(j == k || graph[j][k]) {
						if(j == A[i])
							dp[i][j] = min(dp[i][j],dp[i-1][k]);
						else
							dp[i][j] = min(dp[i][j],dp[i-1][k]+1);
					}
			}
		int ans = dp[n][1];
		for(int i = 1; i <= n1; i++)
			ans = min(ans,dp[n][i]);
		printf("%d\n",ans);
	}
	return 0;
}


#include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #include <windows.h> #define MAX_SALESMEN 4 #define MAX_PRODUCTS 5 #define MAX_DAYS 30 #define FILENAME "sales_data.dat" // 销售记录结构体 typedef struct { int salesman_id; int product_id; double amount; } SaleRecord; // 销售员汇总结构体 typedef struct { int salesman_id; double total_sales; double product_sales[MAX_PRODUCTS]; // 每种产品的销售额 } SalesmanSummary; // 产品汇总结构体 typedef struct { int product_id; double total_sales; } ProductSummary; // 全局变量 SaleRecord records[MAX_DAYS * MAX_SALESMEN]; // 最大记录数 int record_count = 0; SalesmanSummary salesman_summary[MAX_SALESMEN]; ProductSummary product_summary[MAX_PRODUCTS]; // 函数声明 void initSystem(); void mainMenu(); void inputRecords(); void calculateSales(); void sortSalesmen(); void sortProducts(); void displaySalesmen(); void displayProducts(); void saveData(); void loadData(); void clearScreen(); void setColor(int color); void centerText(const char *text); void drawHeader(const char *title); void drawTableHeader(); void drawFooter(); int main() { // 设置控制台窗口大小 system("mode con cols=80 lines=30"); // 初始化系统 initSystem(); // 加载数据 loadData(); // 显示主菜单 mainMenu(); return 0; } // 初始化系统 void initSystem() { // 初始化销售员汇总 for (int i = 0; i < MAX_SALESMEN; i++) { salesman_summary[i].salesman_id = i + 1; salesman_summary[i].total_sales = 0.0; for (int j = 0; j < MAX_PRODUCTS; j++) { salesman_summary[i].product_sales[j] = 0.0; } } // 初始化产品汇总 for (int i = 0; i < MAX_PRODUCTS; i++) { product_summary[i].product_id = i + 1; product_summary[i].total_sales = 0.0; } } // 主菜单 void mainMenu() { int choice; do { clearScreen(); setColor(14); // 黄色 // 绘制菜单框 printf("\n"); centerText("===================================================="); centerText("| 销售管理系统 - 主菜单 |"); centerText("===================================================="); centerText("| |"); centerText("| 1. 录入便条信息 |"); centerText("| 2. 计算每人每种产品的销售额 |"); centerText("| 3. 按销售额对销售员进行排序 |"); centerText("| 4. 按销售额对产品进行排序 |"); centerText("| 5. 显示销售员销售额 |"); centerText("| 6. 显示产品销售额 |"); centerText("| 7. 退出系统 |"); centerText("| |"); centerText("===================================================="); setColor(11); // 浅蓝色 centerText("当前销售记录数: "); printf("%d\n", record_count); setColor(12); // 红色 centerText("请选择操作 (1-7): "); // 获取用户选择 scanf("%d", &choice); switch (choice) { case 1: inputRecords(); break; case 2: calculateSales(); break; case 3: sortSalesmen(); break; case 4: sortProducts(); break; case 5: displaySalesmen(); break; case 6: displayProducts(); break; case 7: saveData(); clearScreen(); centerText("感谢使用销售管理系统!"); centerText("按任意键退出..."); getch(); exit(0); default: setColor(12); centerText("无效选择! 请重新输入."); getch(); } } while (choice != 7); } // 录入便条信息 void inputRecords() { clearScreen(); drawHeader("录入便条信息"); setColor(11); // 浅蓝色 centerText("每天需要录入4位销售员的便条信息"); centerText("--------------------------------"); int day = (record_count / MAX_SALESMEN) + 1; printf("\n"); centerText("正在录入第"); printf("%d", day); centerText("天的销售数据..."); for (int i = 0; i < MAX_SALESMEN; i++) { if (record_count >= MAX_DAYS * MAX_SALESMEN) { setColor(12); // 红色 centerText("已达到最大记录数! 无法继续录入."); getch(); return; } SaleRecord record; int valid = 0; do { printf("\n"); centerText("-- 销售员"); printf("%d", i + 1); centerText(" --"); setColor(15); // 白色 centerText("销售员代号 (1-4): "); scanf("%d", &record.salesman_id); centerText("产品代号 (1-5): "); scanf("%d", &record.product_id); centerText("销售额: "); scanf("%lf", &record.amount); // 验证输入 if (record.salesman_id < 1 || record.salesman_id > MAX_SALESMEN) { setColor(12); centerText("销售员代号无效! 请输入1-4."); valid = 0; } else if (record.product_id < 1 || record.product_id > MAX_PRODUCTS) { setColor(12); centerText("产品代号无效! 请输入1-5."); valid = 0; } else if (record.amount <= 0) { setColor(12); centerText("销售额必须大于0!"); valid = 0; } else { valid = 1; } } while (!valid); // 添加到记录数组 records[record_count++] = record; } // 保存数据 saveData(); setColor(10); // 绿色 centerText("数据录入成功! 按任意键返回..."); getch(); } // 计算每人每种产品的销售额 void calculateSales() { // 重置汇总数据 initSystem(); // 遍历所有记录 for (int i = 0; i < record_count; i++) { SaleRecord record = records[i]; int salesman_idx = record.salesman_id - 1; int product_idx = record.product_id - 1; // 更新销售员汇总 salesman_summary[salesman_idx].total_sales += record.amount; salesman_summary[salesman_idx].product_sales[product_idx] += record.amount; // 更新产品汇总 product_summary[product_idx].total_sales += record.amount; } setColor(10); // 绿色 centerText("销售额计算完成! 按任意键返回..."); getch(); } // 按销售额对销售员进行排序 void sortSalesmen() { // 使用冒泡排序 for (int i = 0; i < MAX_SALESMEN - 1; i++) { for (int j = 0; j < MAX_SALESMEN - i - 1; j++) { if (salesman_summary[j].total_sales < salesman_summary[j + 1].total_sales) { // 交换销售员汇总 SalesmanSummary temp = salesman_summary[j]; salesman_summary[j] = salesman_summary[j + 1]; salesman_summary[j + 1] = temp; } } } setColor(10); // 绿色 centerText("销售员排序完成! 按任意键返回..."); getch(); } // 按销售额对产品进行排序 void sortProducts() { // 使用冒泡排序 for (int i = 0; i < MAX_PRODUCTS - 1; i++) { for (int j = 0; j < MAX_PRODUCTS - i - 1; j++) { if (product_summary[j].total_sales < product_summary[j + 1].total_sales) { // 交换产品汇总 ProductSummary temp = product_summary[j]; product_summary[j] = product_summary[j + 1]; product_summary[j + 1] = temp; } } } setColor(10); // 绿色 centerText("产品排序完成! 按任意键返回..."); getch(); } // 显示销售员销售额 void displaySalesmen() { clearScreen(); drawHeader("销售员销售额汇总"); // 显示表头 setColor(14); // 黄色 printf("\n"); centerText("销售员 | 总销售额 | 产品1 | 产品2 | 产品3 | 产品4 | 产品5"); centerText("-----------------------------------------------------------------"); // 显示每个销售员的数据 setColor(11); // 浅蓝色 for (int i = 0; i < MAX_SALESMEN; i++) { printf(" %d |", salesman_summary[i].salesman_id); printf(" %8.2f |", salesman_summary[i].total_sales); for (int j = 0; j < MAX_PRODUCTS; j++) { printf(" %6.2f |", salesman_summary[i].product_sales[j]); } printf("\n"); } drawFooter(); setColor(12); // 红色 centerText("按任意键返回..."); getch(); } // 显示产品销售额 void displayProducts() { clearScreen(); drawHeader("产品销售额汇总"); // 显示表头 setColor(14); // 黄色 printf("\n"); centerText("产品 | 总销售额 "); centerText("---------------"); // 显示每个产品的数据 setColor(11); // 浅蓝色 for (int i = 0; i < MAX_PRODUCTS; i++) { printf(" %d |", product_summary[i].product_id); printf(" %8.2f \n", product_summary[i].total_sales); } drawFooter(); setColor(12); // 红色 centerText("按任意键返回..."); getch(); } // 保存数据到文件 void saveData() { FILE *file = fopen(FILENAME, "wb"); if (file) { // 保存记录数 fwrite(&record_count, sizeof(int), 1, file); // 保存所有记录 fwrite(records, sizeof(SaleRecord), record_count, file); // 保存销售员汇总 fwrite(salesman_summary, sizeof(SalesmanSummary), MAX_SALESMEN, file); // 保存产品汇总 fwrite(product_summary, sizeof(ProductSummary), MAX_PRODUCTS, file); fclose(file); } } // 从文件加载数据 void loadData() { FILE *file = fopen(FILENAME, "rb"); if (file) { // 加载记录数 fread(&record_count, sizeof(int), 1, file); // 加载所有记录 fread(records, sizeof(SaleRecord), record_count, file); // 加载销售员汇总 fread(salesman_summary, sizeof(SalesmanSummary), MAX_SALESMEN, file); // 加载产品汇总 fread(product_summary, sizeof(ProductSummary), MAX_PRODUCTS, file); fclose(file); } } // 清除屏幕 void clearScreen() { system("cls"); } // 设置文本颜色 void setColor(int color) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color); } // 居中显示文本 void centerText(const char *text) { int len = strlen(text); int padding = (80 - len) / 2; for (int i = 0; i < padding; i++) printf(" "); printf("%s\n", text); } // 绘制标题 void drawHeader(const char *title) { setColor(14); // 黄色 centerText("===================================================="); centerText("| 销售管理系统 |"); centerText("===================================================="); centerText("| |"); printf("|%*s%*s|\n", (80 - strlen(title) - 2) / 2 + strlen(title), title, (80 - strlen(title) - 2) / 2, ""); centerText("| |"); centerText("===================================================="); } // 绘制表尾 void drawFooter() { setColor(14); // 黄色 centerText("===================================================="); } 帮我分析上述代码
最新发布
07-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值