UVA10271_Chopsticks

本文探讨了一道关于从已知长度的筷子中选择特定组合以达到最小质量的问题,并通过动态规划方法给出了详细的解决思路及代码实现。

Chopsticks

大致就是有一堆筷子,知道了他们的长度,现在选长度为abc的三个筷子a<=b<=c为一对筷子,质量为(a-b)平方,现在选k双这样的筷子,求质量最小

思路:

第一次看到这个题目,人太弱完全没思路,因为之前状态转移都会有一个明显的子局面或者可以根据新增的i+1变量就行状态转移,可是这一题,一直想不出来如何转移,以为新增的筷子可以是a或b或c,但后面看了题解之后发现,人弱能怪谁!!!这题在最开始状态就很模糊没有建好,而且转移的时候还有技巧

应该这样建dp[i][k]就是前i个筷子组成k双筷子,那么为了方便状态的转移并且使用贪心可以先sort一下从大到小排,并且设定选取筷子的时候默认是再选a,同时他的前一个就是b,这样c只要位于b的前面就行了,c对质量无影响.那么问题来了,万一这样选不存在c了怎么办,所以转移的时候如果j<i*3那么肯定不存在,不进行转移!!!!!!

则转移方程为

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<stack>
#include<map>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 5e3+100;
const int INF = 0x3f3f3f3f;
int a[maxn],dp[maxn][maxn];
int main(){
#ifdef LOCAL
    freopen("in.txt","r",stdin);
   // freopen("out.txt","w",stdout);
 #endif
    int t,n,k;
    cin>>t;
    while(t--){
        cin>>k>>n;k+=8;
        for(int i=n;i>0;--i) cin>>a[i];
        for(int i=1;i<=n;i++){
            dp[i][0]=0;
            for(int j=1;j<=k;j++){
                dp[i][j]=INF;
            }
        }
        for(int i=3;i<=n;i++){
            for(int j=1;j<=k;j++){
                if(i>=j*3&&dp[i-2][j-1]!=INF){
                    dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]));
                }
            }
        }
        cout<<dp[n][k]<<endl;

    }
    return 0;
}



import threading import time import random # 线程安全的打印函数 def thread_safe_print(message): with threading.Lock(): print(message) class Chopstick: def __init__(self, id): self.id = id self.lock = threading.Lock() def pick_up(self): """尝试拿起筷子,成功返回True,失败返回False""" return self.lock.acquire(blocking=False) def put_down(self): """放下筷子""" self.lock.release() class Philosopher(threading.Thread): def __init__(self, pid, left_chopstick, right_chopstick): super().__init__() self.pid = pid self.left_chopstick = left_chopstick self.right_chopstick = right_chopstick self.is_running = True def run(self): while self.is_running: self.think() self.dine() def think(self): thread_safe_print(f"哲学家 {self.pid} 正在思考") time.sleep(random.uniform(1, 3)) def dine(self): # 按序号获取筷子 first, second = self.get_chopsticks_in_order() thread_safe_print(f"哲学家 {self.pid} 尝试获取筷子 {first.id}") has_first = first.pick_up() if has_first: try: thread_safe_print(f"哲学家 {self.pid} 已获取筷子 {first.id},尝试获取筷子 {second.id}") time.sleep(0.1) # 增加上下文切换机会,暴露潜在问题 has_second = second.pick_up() if has_second: try: thread_safe_print(f"哲学家 {self.pid} 开始用餐") time.sleep(random.uniform(1, 2)) finally: second.put_down() thread_safe_print(f"哲学家 {self.pid} 放下筷子 {second.id}") else: thread_safe_print(f"哲学家 {self.pid} 未能获取筷子 {second.id}") finally: first.put_down() thread_safe_print(f"哲学家 {self.pid} 放下筷子 {first.id}") else: thread_safe_print(f"哲学家 {self.pid} 未能获取筷子 {first.id}") def get_chopsticks_in_order(self): if self.left_chopstick.id < self.right_chopstick.id: return self.left_chopstick, self.right_chopstick else: return self.right_chopstick, self.left_chopstick def stop(self): """停止哲学家线程""" self.is_running = False def main(): # 创建筷子 chopsticks = [Chopstick(i) for i in range(5)] # 创建哲学家 philosophers = [ Philosopher(0, chopsticks[0], chopsticks[1]), Philosopher(1, chopsticks[1], chopsticks[2]), Philosopher(2, chopsticks[2], chopsticks[3]), Philosopher(3, chopsticks[3], chopsticks[4]), Philosopher(4, chopsticks[4], chopsticks[0]), ] # 启动所有哲学家线程 for p in philosophers: p.start() thread_safe_print(f"哲学家 {p.pid} 已开始思考...") try: # 运行一段时间后停止 thread_safe_print("\n哲学家们开始他们的思考和用餐循环...") thread_safe_print("程序将运行30秒后自动退出...\n") time.sleep(30) except KeyboardInterrupt: thread_safe_print("\n程序被用户中断") finally: # 优雅地停止所有线程 thread_safe_print("\n正在停止所有哲学家线程...") for p in philosophers: p.stop() p.join(timeout=1.0) thread_safe_print("所有哲学家已停止思考和用餐。") if __name__ == "__main__": main()
05-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值